diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2a0b9df..a1ddc6c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -50,6 +50,26 @@ updates: prefix: "chore(deps)" rebase-strategy: "disabled" + - package-ecosystem: pip + directory: "/examples/servers/mcpdoc" + schedule: + interval: monthly + open-pull-requests-limit: 10 + versioning-strategy: increase + commit-message: + prefix: "chore(deps)" + rebase-strategy: "disabled" + + - package-ecosystem: pip + directory: "/examples/servers/mcpdoc/function" + schedule: + interval: monthly + open-pull-requests-limit: 10 + versioning-strategy: increase + commit-message: + prefix: "chore(deps)" + rebase-strategy: "disabled" + - package-ecosystem: npm directory: "/src/typescript" schedule: @@ -80,6 +100,16 @@ updates: prefix: "chore(deps)" rebase-strategy: "disabled" + - package-ecosystem: npm + directory: "/examples/servers/cat-facts" + schedule: + interval: monthly + open-pull-requests-limit: 10 + versioning-strategy: increase + commit-message: + prefix: "chore(deps)" + rebase-strategy: "disabled" + - package-ecosystem: npm directory: "/e2e_tests/typescript" schedule: diff --git a/.github/workflows/cdk-checks.yml b/.github/workflows/cdk-checks.yml index e678608..2645f12 100644 --- a/.github/workflows/cdk-checks.yml +++ b/.github/workflows/cdk-checks.yml @@ -40,6 +40,42 @@ jobs: env: CDK_DEFAULT_ACCOUNT: "000000000000" + check_mcpdoc_server: + name: Check Python-based MCP Doc Server + runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + + - name: "Set up Typescript" + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: "Set up Python" + uses: actions/setup-python@v5 + with: + python-version-file: "src/python/.python-version" + + - name: Install CDK CLI + run: npm install -g aws-cdk + + - name: Install dependencies + run: pip install -r requirements.txt + working-directory: ./examples/servers/mcpdoc + + - uses: pypa/gh-action-pip-audit@v1.1.0 + with: + inputs: ./examples/servers/mcpdoc/requirements.txt + + - name: Synthesize CDK stack + run: cdk synth --app 'python3 cdk_stack.py' + working-directory: ./examples/servers/mcpdoc + env: + CDK_DEFAULT_ACCOUNT: "000000000000" + check_weather_alerts_server: name: Check Typescript-based Weather Alerts Server runs-on: ubuntu-latest @@ -81,3 +117,45 @@ jobs: working-directory: ./examples/servers/weather-alerts env: CDK_DEFAULT_ACCOUNT: "000000000000" + + check_cat_facts_server: + name: Check Typescript-based Cat Facts Server + runs-on: ubuntu-latest + permissions: + contents: read + timeout-minutes: 15 + steps: + - uses: actions/checkout@v4 + + - name: "Set up Typescript" + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install CDK CLI + run: npm install -g aws-cdk + + - name: Build and link local package + run: | + npm ci + npm audit --audit-level critical + npm run build + npm link + working-directory: ./src/typescript + + - name: Install dependencies + run: | + npm ci + npm audit --audit-level critical + npm link @aws/run-mcp-servers-with-aws-lambda + working-directory: ./examples/servers/cat-facts + + - name: Build + run: npm run build + working-directory: ./examples/servers/cat-facts + + - name: Synthesize CDK stack + run: cdk synth --app 'node lib/cat-facts-mcp-server.js' + working-directory: ./examples/servers/cat-facts + env: + CDK_DEFAULT_ACCOUNT: "000000000000" diff --git a/.mergify.yml b/.mergify.yml index 4a3c2fc..9035c23 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -15,7 +15,9 @@ queue_rules: - status-success=Check Python library - status-success=Check Typescript library - status-success=Check Python-based Time Server + - status-success=Check Python-based MCP Doc Server - status-success=Check Typescript-based Weather Alerts Server + - status-success=Check Typescript-based Cat Facts Server - status-success=Check Typescript chatbot merge_method: squash diff --git a/e2e_tests/clean_up_integ_test.sh b/e2e_tests/clean_up_integ_test.sh index bab56ac..9d5d80c 100755 --- a/e2e_tests/clean_up_integ_test.sh +++ b/e2e_tests/clean_up_integ_test.sh @@ -15,5 +15,11 @@ export INTEG_TEST_ID=$(cat e2e_tests/integ-test-id) cd examples/servers/time cdk destroy --force --app 'python3 cdk_stack.py' +cd ../mcpdoc +cdk destroy --force --app 'python3 cdk_stack.py' + cd ../weather-alerts/ cdk destroy --force --app 'node lib/weather-alerts-mcp-server.js' + +cd ../cat-facts/ +cdk destroy --force --app 'node lib/cat-facts-mcp-server.js' diff --git a/e2e_tests/python/main.py b/e2e_tests/python/main.py index 1e2d7a3..5fdafcb 100644 --- a/e2e_tests/python/main.py +++ b/e2e_tests/python/main.py @@ -79,6 +79,8 @@ async def main() -> None: "Hello!", "What is the current time in Seattle?", "Are there any weather alerts right now?", + "What documentation sources can you use to answer questions?", + "Tell me a cat fact.", "Who is Tom Cruise?", ] chat_session = ChatSession(servers, llm_client, user_utterances) diff --git a/e2e_tests/run_integ_test.sh b/e2e_tests/run_integ_test.sh index c8c0661..676e215 100755 --- a/e2e_tests/run_integ_test.sh +++ b/e2e_tests/run_integ_test.sh @@ -17,6 +17,11 @@ cd ../../examples/servers/time uv pip install -r requirements.txt cdk deploy --app 'python3 cdk_stack.py' +# Deploy Python-based mcpdoc MCP server +cd ../mcpdoc +uv pip install -r requirements.txt +cdk deploy --app 'python3 cdk_stack.py' + # Deploy Typescript-based example MCP server cd ../../../src/typescript/ npm ci @@ -29,6 +34,13 @@ npm link @aws/run-mcp-servers-with-aws-lambda npm run build cdk deploy --app 'node lib/weather-alerts-mcp-server.js' +# Deploy Typescript-based cat-facts MCP server +cd ../cat-facts/ +npm ci +npm link @aws/run-mcp-servers-with-aws-lambda +npm run build +cdk deploy --app 'node lib/cat-facts-mcp-server.js' + # Configure integ tests cd ../../../e2e_tests/ sed "s/INTEG_TEST_ID/$INTEG_TEST_ID/g" servers_config.integ.json > python/servers_config.json diff --git a/e2e_tests/servers_config.integ.json b/e2e_tests/servers_config.integ.json index 89b2a8d..08ba2d6 100644 --- a/e2e_tests/servers_config.integ.json +++ b/e2e_tests/servers_config.integ.json @@ -13,6 +13,14 @@ "weatherAlerts": { "functionName": "mcp-server-weather-alerts-INTEG_TEST_ID", "region": "us-east-2" + }, + "mcpdoc": { + "functionName": "mcp-server-mcpdoc-INTEG_TEST_ID", + "region": "us-east-2" + }, + "catFacts": { + "functionName": "mcp-server-cat-facts-INTEG_TEST_ID", + "region": "us-east-2" } } } diff --git a/e2e_tests/typescript/src/main.ts b/e2e_tests/typescript/src/main.ts index 9128ba6..f7689ab 100644 --- a/e2e_tests/typescript/src/main.ts +++ b/e2e_tests/typescript/src/main.ts @@ -33,6 +33,8 @@ async function main(): Promise { "Hello!", "What is the current time in Seattle?", "Are there any weather alerts right now?", + "What documentation sources can you use to answer questions?", + "Tell me a cat fact.", "Who is Tom Cruise?", ]; diff --git a/examples/chatbots/python/servers_config.json b/examples/chatbots/python/servers_config.json index 28bab57..5557186 100644 --- a/examples/chatbots/python/servers_config.json +++ b/examples/chatbots/python/servers_config.json @@ -13,6 +13,14 @@ "weatherAlerts": { "functionName": "mcp-server-weather-alerts", "region": "us-east-2" + }, + "mcpdoc": { + "functionName": "mcp-server-mcpdoc", + "region": "us-east-2" + }, + "catFacts": { + "functionName": "mcp-server-cat-facts", + "region": "us-east-2" } } } diff --git a/examples/chatbots/typescript/servers_config.json b/examples/chatbots/typescript/servers_config.json index 28bab57..5557186 100644 --- a/examples/chatbots/typescript/servers_config.json +++ b/examples/chatbots/typescript/servers_config.json @@ -13,6 +13,14 @@ "weatherAlerts": { "functionName": "mcp-server-weather-alerts", "region": "us-east-2" + }, + "mcpdoc": { + "functionName": "mcp-server-mcpdoc", + "region": "us-east-2" + }, + "catFacts": { + "functionName": "mcp-server-cat-facts", + "region": "us-east-2" } } } diff --git a/examples/servers/cat-facts/.npmignore b/examples/servers/cat-facts/.npmignore new file mode 100644 index 0000000..c1d6d45 --- /dev/null +++ b/examples/servers/cat-facts/.npmignore @@ -0,0 +1,6 @@ +*.ts +!*.d.ts + +# CDK asset staging directory +.cdk.staging +cdk.out diff --git a/examples/servers/cat-facts/README.md b/examples/servers/cat-facts/README.md new file mode 100644 index 0000000..e48dfb0 --- /dev/null +++ b/examples/servers/cat-facts/README.md @@ -0,0 +1,21 @@ +Sample inputs: + +```bash +$ npm run build +$ export LOG_LEVEL=debug + +# Initialize +$ node -e 'require("./lib/cat-facts-mcp-server.function.js").handler({"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"roots":{"listChanged":true}},"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}, "")' + +# List tools +$ node -e 'require("./lib/cat-facts-mcp-server.function.js").handler({"method":"tools/list","params":{"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}, "")' + +# Get a random cat fact +$ node -e 'require("./lib/cat-facts-mcp-server.function.js").handler({"method":"tools/call","params":{"name":"getRandomFact","arguments":{}},"jsonrpc":"2.0","id":0}, "")' + +# Get cat breeds +$ node -e 'require("./lib/cat-facts-mcp-server.function.js").handler({"method":"tools/call","params":{"name":"getBreeds","arguments":{"limit":5}},"jsonrpc":"2.0","id":0}, "")' + +# Get multiple cat facts +$ node -e 'require("./lib/cat-facts-mcp-server.function.js").handler({"method":"tools/call","params":{"name":"getFacts","arguments":{"limit":3,"max_length":100}},"jsonrpc":"2.0","id":0}, "")' +``` diff --git a/examples/servers/cat-facts/cat-facts-openapi.json b/examples/servers/cat-facts/cat-facts-openapi.json new file mode 100644 index 0000000..d032d90 --- /dev/null +++ b/examples/servers/cat-facts/cat-facts-openapi.json @@ -0,0 +1,212 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Cat Fact API", + "description": "An API for facts about cats", + "contact": { + "email": "contact@catfact.ninja" + }, + "version": "1.0.0" + }, + "servers": [ + { + "url": "https://catfact.ninja" + } + ], + "paths": { + "/breeds": { + "get": { + "tags": [ + "Breeds" + ], + "summary": "Get a list of breeds", + "description": "Returns a a list of breeds", + "operationId": "getBreeds", + "parameters": [ + { + "name": "limit", + "in": "query", + "description": "limit the amount of results returned", + "required": false, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Breed" + } + } + } + } + } + } + } + }, + "/fact": { + "get": { + "tags": [ + "Facts" + ], + "summary": "Get Random Fact", + "description": "Returns a random fact", + "operationId": "getRandomFact", + "parameters": [ + { + "name": "max_length", + "in": "query", + "description": "maximum length of returned fact", + "required": false, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CatFact" + } + } + } + }, + "404": { + "description": "Fact not found" + } + } + } + }, + "/facts": { + "get": { + "tags": [ + "Facts" + ], + "summary": "Get a list of facts", + "description": "Returns a a list of facts", + "operationId": "getFacts", + "parameters": [ + { + "name": "max_length", + "in": "query", + "description": "maximum length of returned fact", + "required": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "limit", + "in": "query", + "description": "limit the amount of results returned", + "required": false, + "schema": { + "type": "integer", + "format": "int64" + } + } + ], + "responses": { + "200": { + "description": "successful operation", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CatFact" + } + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "Breed": { + "title": "Breed model", + "description": "Breed", + "properties": { + "breed": { + "title": "Breed", + "description": "Breed", + "type": "string", + "format": "string" + }, + "country": { + "title": "Country", + "description": "Country", + "type": "string", + "format": "string" + }, + "origin": { + "title": "Origin", + "description": "Origin", + "type": "string", + "format": "string" + }, + "coat": { + "title": "Coat", + "description": "Coat", + "type": "string", + "format": "string" + }, + "pattern": { + "title": "Pattern", + "description": "Pattern", + "type": "string", + "format": "string" + } + }, + "type": "object" + }, + "CatFact": { + "title": "CatFact model", + "description": "CatFact", + "properties": { + "fact": { + "title": "Fact", + "description": "Fact", + "type": "string", + "format": "string" + }, + "length": { + "title": "Length", + "description": "Length", + "type": "integer", + "format": "int32" + } + }, + "type": "object" + } + } + }, + "tags": [ + { + "name": "Facts", + "description": "Cat Facts" + }, + { + "name": "Breeds", + "description": "Breeds" + } + ], + "security": [ + [] + ] +} diff --git a/examples/servers/cat-facts/lib/cat-facts-mcp-server.function.ts b/examples/servers/cat-facts/lib/cat-facts-mcp-server.function.ts new file mode 100644 index 0000000..cfb9d43 --- /dev/null +++ b/examples/servers/cat-facts/lib/cat-facts-mcp-server.function.ts @@ -0,0 +1,15 @@ +import { Handler, Context } from "aws-lambda"; + +const serverParams = { + command: "npx", + args: ["--offline", "openapi-mcp-server", "./cat-facts-openapi.json"], +}; + +export const handler: Handler = async (event, context: Context) => { + // Dynamically import ES module into CommonJS Lambda function + const { stdioServerAdapter } = await import( + "@aws/run-mcp-servers-with-aws-lambda" + ); + + return await stdioServerAdapter(serverParams, event, context); +}; diff --git a/examples/servers/cat-facts/package-lock.json b/examples/servers/cat-facts/package-lock.json new file mode 100644 index 0000000..1dfe107 --- /dev/null +++ b/examples/servers/cat-facts/package-lock.json @@ -0,0 +1,707 @@ +{ + "name": "cat-facts", + "version": "0.2.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cat-facts", + "version": "0.2.1", + "dependencies": { + "@types/aws-lambda": "^8.10.149", + "aws-cdk-lib": "2.199.0", + "constructs": "^10.0.0", + "openapi-mcp-server": "^2.0.3" + }, + "devDependencies": { + "@types/node": "22.15.24", + "aws-cdk": "2.1017.0", + "cdk-nag": "^2.36.2", + "typescript": "~5.8.3" + } + }, + "node_modules/@aws-cdk/asset-awscli-v1": { + "version": "2.2.237", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.237.tgz", + "integrity": "sha512-OlXylbXI52lboFVJBFLae+WB99qWmI121x/wXQHEMj2RaVNVbWE+OAHcDk2Um1BitUQCaTf9ki57B0Fuqx0Rvw==", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/asset-node-proxy-agent-v6": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.0.tgz", + "integrity": "sha512-7bY3J8GCVxLupn/kNmpPc5VJz8grx+4RKfnnJiO1LG+uxkZfANZG3RMHhE+qQxxwkyQ9/MfPtTpf748UhR425A==", + "license": "Apache-2.0" + }, + "node_modules/@aws-cdk/cloud-assembly-schema": { + "version": "41.2.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-41.2.0.tgz", + "integrity": "sha512-JaulVS6z9y5+u4jNmoWbHZRs9uGOnmn/ktXygNWKNu1k6lF3ad4so3s18eRu15XCbUIomxN9WPYT6Ehh7hzONw==", + "bundleDependencies": [ + "jsonschema", + "semver" + ], + "license": "Apache-2.0", + "dependencies": { + "jsonschema": "~1.4.1", + "semver": "^7.7.1" + }, + "engines": { + "node": ">= 14.15.0" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": { + "version": "1.4.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": { + "version": "7.7.1", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-0.6.1.tgz", + "integrity": "sha512-OkVXMix3EIbB5Z6yife2XTrSlOnVvCLR1Kg91I4pYFEsV9RbnoyQVScXCuVhGaZHOnTZgso8lMQN1Po2TadGKQ==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "raw-body": "^3.0.0", + "zod": "^3.23.8" + } + }, + "node_modules/@types/aws-lambda": { + "version": "8.10.150", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.150.tgz", + "integrity": "sha512-AX+AbjH/rH5ezX1fbK8onC/a+HyQHo7QGmvoxAE42n22OsciAxvZoZNEr22tbXs8WfP1nIsBjKDpgPm3HjOZbA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.24.tgz", + "integrity": "sha512-w9CZGm9RDjzTh/D+hFwlBJ3ziUaVw7oufKA3vOFSOZlzmW9AkZnfjPb+DLnrV6qtgL/LNmP0/2zBNCFHL3F0ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/aws-cdk": { + "version": "2.1017.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1017.0.tgz", + "integrity": "sha512-KnpU9kOCR1k2tAcpYoqtIdq7UqKVX4ooNrGJq+dXUKRnIwQr66tSe5YEoeQGYxImAHv1LuZAyAAm5DcEPhbjNg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "cdk": "bin/cdk" + }, + "engines": { + "node": ">= 14.15.0" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/aws-cdk-lib": { + "version": "2.199.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.199.0.tgz", + "integrity": "sha512-hAZHdb7bPHepIGpuyg0jS/F3toY7VRvJDqxo4+C2cYY5zvktGP3lgcC9ukE2ehxYU1Pa9YOAehEDIxrita0Hvw==", + "bundleDependencies": [ + "@balena/dockerignore", + "case", + "fs-extra", + "ignore", + "jsonschema", + "minimatch", + "punycode", + "semver", + "table", + "yaml", + "mime-types" + ], + "license": "Apache-2.0", + "dependencies": { + "@aws-cdk/asset-awscli-v1": "2.2.237", + "@aws-cdk/asset-node-proxy-agent-v6": "^2.1.0", + "@aws-cdk/cloud-assembly-schema": "^41.2.0", + "@balena/dockerignore": "^1.0.2", + "case": "1.6.3", + "fs-extra": "^11.3.0", + "ignore": "^5.3.2", + "jsonschema": "^1.5.0", + "mime-types": "^2.1.35", + "minimatch": "^3.1.2", + "punycode": "^2.3.1", + "semver": "^7.7.2", + "table": "^6.9.0", + "yaml": "1.10.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "constructs": "^10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": { + "version": "1.0.2", + "inBundle": true, + "license": "Apache-2.0" + }, + "node_modules/aws-cdk-lib/node_modules/ajv": { + "version": "8.17.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-regex": { + "version": "5.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/ansi-styles": { + "version": "4.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/astral-regex": { + "version": "2.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/balanced-match": { + "version": "1.0.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/brace-expansion": { + "version": "1.1.11", + "inBundle": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/aws-cdk-lib/node_modules/case": { + "version": "1.6.3", + "inBundle": true, + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-convert": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/color-name": { + "version": "1.1.4", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/concat-map": { + "version": "0.0.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/emoji-regex": { + "version": "8.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": { + "version": "3.1.3", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/fast-uri": { + "version": "3.0.6", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "inBundle": true, + "license": "BSD-3-Clause" + }, + "node_modules/aws-cdk-lib/node_modules/fs-extra": { + "version": "11.3.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/aws-cdk-lib/node_modules/graceful-fs": { + "version": "4.2.11", + "inBundle": true, + "license": "ISC" + }, + "node_modules/aws-cdk-lib/node_modules/ignore": { + "version": "5.3.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": { + "version": "1.0.0", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/jsonfile": { + "version": "6.1.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/jsonschema": { + "version": "1.5.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/lodash.truncate": { + "version": "4.4.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/minimatch": { + "version": "3.1.2", + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/aws-cdk-lib/node_modules/punycode": { + "version": "2.3.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/aws-cdk-lib/node_modules/require-from-string": { + "version": "2.0.2", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/semver": { + "version": "7.7.2", + "inBundle": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aws-cdk-lib/node_modules/slice-ansi": { + "version": "4.0.0", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/aws-cdk-lib/node_modules/string-width": { + "version": "4.2.3", + "inBundle": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/strip-ansi": { + "version": "6.0.1", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/aws-cdk-lib/node_modules/table": { + "version": "6.9.0", + "inBundle": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/universalify": { + "version": "2.0.1", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aws-cdk-lib/node_modules/yaml": { + "version": "1.10.2", + "inBundle": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cdk-nag": { + "version": "2.36.24", + "resolved": "https://registry.npmjs.org/cdk-nag/-/cdk-nag-2.36.24.tgz", + "integrity": "sha512-swrTkaUIgVHINIuoVM766lUMUHrJWMHG2aknAfz1jroTiDHe+7myYKdyIwJoelzcHmPsJzCiDWFD3j0duGCP3g==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "aws-cdk-lib": "^2.156.0", + "constructs": "^10.0.5" + } + }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/constructs": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.4.2.tgz", + "integrity": "sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==", + "license": "Apache-2.0" + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/openapi-mcp-server": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/openapi-mcp-server/-/openapi-mcp-server-2.0.3.tgz", + "integrity": "sha512-G9bKEsFFj9xHlbXElgg3UsvLdEiWgD8HVHjgHbBWywfbRl0FbVXHeto1B0mSR5d4Ri1aWlA7ZdTS2rQv2xkoAg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "^0.6.0", + "chalk": "^5.3.0", + "dotenv": "^16.4.5", + "undici": "^5.28.4" + }, + "bin": { + "openapi-mcp-server": "index.js", + "slop-mcp": "index.js" + }, + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/examples/servers/cat-facts/package.json b/examples/servers/cat-facts/package.json new file mode 100644 index 0000000..dcc20c4 --- /dev/null +++ b/examples/servers/cat-facts/package.json @@ -0,0 +1,23 @@ +{ + "name": "cat-facts", + "version": "0.2.1", + "main": "lib/cat-facts-mcp-server.js", + "types": "lib/cat-facts-mcp-server.d.ts", + "scripts": { + "build": "tsc", + "watch": "tsc -w", + "cdk": "cdk" + }, + "devDependencies": { + "@types/node": "22.15.24", + "aws-cdk": "2.1017.0", + "cdk-nag": "^2.36.2", + "typescript": "~5.8.3" + }, + "dependencies": { + "@types/aws-lambda": "^8.10.149", + "aws-cdk-lib": "2.199.0", + "constructs": "^10.0.0", + "openapi-mcp-server": "^2.0.3" + } +} diff --git a/examples/servers/cat-facts/tsconfig.json b/examples/servers/cat-facts/tsconfig.json new file mode 100644 index 0000000..fc44377 --- /dev/null +++ b/examples/servers/cat-facts/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": [ + "es2020" + ], + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "noImplicitThis": true, + "alwaysStrict": true, + "noUnusedLocals": false, + "noUnusedParameters": false, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": false, + "inlineSourceMap": true, + "inlineSources": true, + "experimentalDecorators": true, + "strictPropertyInitialization": false, + "typeRoots": [ + "./node_modules/@types" + ] + }, + "exclude": [ + "node_modules", + "cdk.out" + ] +} diff --git a/examples/servers/mcpdoc/README.md b/examples/servers/mcpdoc/README.md new file mode 100644 index 0000000..2f5955a --- /dev/null +++ b/examples/servers/mcpdoc/README.md @@ -0,0 +1,31 @@ +# mcpdoc MCP Server Lambda Example + +This example demonstrates running the [mcpdoc MCP server](https://github.com/langchain-ai/mcpdoc) in AWS Lambda. +The mcpdoc server provides access to documentation via llms.txt files. + +## Sample inputs + +```bash +uv pip install -r function/requirements.txt + +# Initialize +$ python -c 'from function import index; print(index.handler({"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{"roots":{"listChanged":True}},"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}, ""))' + +# List tools +$ python -c 'from function import index; print(index.handler({"method":"tools/list","params":{"clientInfo":{"name":"mcp","version":"0.1.0"}},"jsonrpc":"2.0","id":0}, ""))' + +# List documentation sources +$ python -c 'from function import index; print(index.handler({"method":"tools/invoke","params":{"name":"list_doc_sources","parameters":{}},"jsonrpc":"2.0","id":0}, ""))' + +# Fetch documentation +$ python -c 'from function import index; print(index.handler({"method":"tools/invoke","params":{"name":"fetch_docs","parameters":{"url":"https://strandsagents.com/latest/llms.txt"}},"jsonrpc":"2.0","id":0}, ""))' +``` + +## Configuration + +The mcpdoc server is configured with the following options: + +- `--urls`: Specifies the llms.txt files to use, in the format `Name:URL`. In this example, we use `Strands:https://strandsagents.com/latest/llms.txt`. +- `--allowed-domains`: Specifies which domains the server is allowed to fetch documentation from. In this example, we allow `strandsagents.com`. + +For more configuration options, see the [mcpdoc GitHub repository](https://github.com/langchain-ai/mcpdoc). diff --git a/examples/servers/mcpdoc/cdk_stack.py b/examples/servers/mcpdoc/cdk_stack.py new file mode 100644 index 0000000..f5e0cf2 --- /dev/null +++ b/examples/servers/mcpdoc/cdk_stack.py @@ -0,0 +1,101 @@ +from aws_cdk import ( + App, + Aspects, + DockerVolume, + Environment, + RemovalPolicy, + Stack, + aws_iam as iam, + aws_lambda as lambda_, + aws_lambda_python_alpha as lambda_python, + aws_logs as logs, +) +from cdk_nag import AwsSolutionsChecks +from constructs import Construct +import jsii +import os + + +# For testing, the run-mcp-servers-with-aws-lambda module is built and bundled +# from local files. Remove these command hooks if using the +# run-mcp-servers-with-aws-lambda from PyPi. +@jsii.implements(lambda_python.ICommandHooks) +class CommandHooks: + @jsii.member(jsii_name="afterBundling") + def after_bundling(self, input_dir: str, output_dir: str) -> list[str]: + return [ + f"cd {output_dir}", + f"curl -LsSf https://astral.sh/uv/install.sh | env UV_UNMANAGED_INSTALL='{output_dir}' sh", + f"mkdir {output_dir}/mcp_lambda_build", + f"cp /mcp_lambda_src/README.md {output_dir}/mcp_lambda_build/README.md", + f"cp /mcp_lambda_src/pyproject.toml {output_dir}/mcp_lambda_build/pyproject.toml", + f"cp /mcp_lambda_src/uv.lock {output_dir}/mcp_lambda_build/uv.lock", + f"cp -r /mcp_lambda_src/src {output_dir}/mcp_lambda_build/src", + f"UV_CACHE_DIR={output_dir}/.cache UV_DYNAMIC_VERSIONING_BYPASS=0.0.1 {output_dir}/uv build --wheel --directory {output_dir}/mcp_lambda_build", + f"python -m pip install {output_dir}/mcp_lambda_build/dist/*.whl -t {output_dir}", + f"rm -r {output_dir}/mcp_lambda_build {output_dir}/.cache uv", + ] + + @jsii.member(jsii_name="beforeBundling") + def before_bundling(self, input_dir: str, output_dir: str) -> list[str]: + return [] + + +class LambdaMcpdocMcpServer(Stack): + def __init__( + self, scope: Construct, construct_id: str, stack_name_suffix: str, **kwargs + ) -> None: + super().__init__(scope, construct_id, **kwargs) + + log_group = logs.LogGroup( + self, + "ServerFunctionLogGroup", + log_group_name=f"mcp-server-mcpdoc{stack_name_suffix}", + retention=logs.RetentionDays.ONE_DAY, + removal_policy=RemovalPolicy.DESTROY, + ) + + lambda_python.PythonFunction( + self, + "ServerFunction", + function_name="mcp-server-mcpdoc" + stack_name_suffix, + role=iam.Role.from_role_name(self, "Role", "mcp-lambda-example-servers"), + log_group=log_group, + runtime=lambda_.Runtime.PYTHON_3_13, + entry="function", + memory_size=2048, + timeout=lambda_.Duration.seconds(30), + environment={ + "LOG_LEVEL": "DEBUG", + }, + # For testing, the run-mcp-servers-with-aws-lambda module is built and bundled + # from local files. Remove the bundling configuration if using the + # run-mcp-servers-with-aws-lambda from PyPi. + bundling=lambda_python.BundlingOptions( + # asset_excludes=[".venv", ".mypy_cache", "__pycache__"], + volumes=[ + DockerVolume( + container_path="/mcp_lambda_src", + # Assume we're in examples/servers/mcpdoc dir + host_path=os.path.join(os.getcwd(), "../../../src/python"), + ) + ], + command_hooks=CommandHooks(), + ), + ) + + +app = App() +env = Environment(account=os.environ["CDK_DEFAULT_ACCOUNT"], region="us-east-2") +stack_name_suffix = ( + f'-{os.environ["INTEG_TEST_ID"]}' if "INTEG_TEST_ID" in os.environ else "" +) +stack = LambdaMcpdocMcpServer( + app, + "LambdaMcpServer-Mcpdoc", + stack_name_suffix, + stack_name="LambdaMcpServer-Mcpdoc" + stack_name_suffix, + env=env, +) +Aspects.of(stack).add(AwsSolutionsChecks(verbose=True)) +app.synth() diff --git a/examples/servers/mcpdoc/function/__init__.py b/examples/servers/mcpdoc/function/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/examples/servers/mcpdoc/function/__init__.py @@ -0,0 +1 @@ + diff --git a/examples/servers/mcpdoc/function/index.py b/examples/servers/mcpdoc/function/index.py new file mode 100644 index 0000000..7ba4843 --- /dev/null +++ b/examples/servers/mcpdoc/function/index.py @@ -0,0 +1,17 @@ +import sys +from mcp.client.stdio import StdioServerParameters +from mcp_lambda import stdio_server_adapter + +server_params = StdioServerParameters( + command=sys.executable, + args=[ + "-m", + "mcpdoc", + "--urls", "Strands:https://strandsagents.com/latest/llms.txt", + "--allowed-domains", "strandsagents.com", + ], +) + + +def handler(event, context): + return stdio_server_adapter(server_params, event, context) diff --git a/examples/servers/mcpdoc/function/requirements.txt b/examples/servers/mcpdoc/function/requirements.txt new file mode 100644 index 0000000..7fa9238 --- /dev/null +++ b/examples/servers/mcpdoc/function/requirements.txt @@ -0,0 +1,5 @@ +mcpdoc + +# For testing, this module is installed from local files. +# Uncomment this line to build using the module from PyPi +# run-mcp-servers-with-aws-lambda >= 0.0.1 diff --git a/examples/servers/mcpdoc/requirements.txt b/examples/servers/mcpdoc/requirements.txt new file mode 100644 index 0000000..3cf365f --- /dev/null +++ b/examples/servers/mcpdoc/requirements.txt @@ -0,0 +1,4 @@ +aws-cdk-lib==2.199.0 +aws-cdk.aws-lambda-python-alpha==2.199.0a0 +constructs>=10.0.0,<11.0.0 +cdk-nag==2.36.2