@bluefly/openstandardagents 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +41 -0
- package/.eslintrc.cjs +43 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +39 -0
- package/.github/dependabot.yml +58 -0
- package/.github/workflows/ci.yml +154 -0
- package/.github/workflows/codeql.yml +41 -0
- package/.github/workflows/dependabot-auto-merge.yml +28 -0
- package/.github/workflows/release.yml +103 -0
- package/.prettierignore +7 -0
- package/.prettierrc.json +10 -0
- package/.redocly.yaml +9 -0
- package/.releaserc.json +84 -0
- package/.releaserc.json.disabled +81 -0
- package/CHANGELOG.md +152 -0
- package/CONTRIBUTING.md +249 -0
- package/LICENSE +190 -0
- package/README.md +280 -0
- package/bin/ossa +8 -0
- package/bin/validate-ossa-0.2.2.ts +244 -0
- package/dist/di-container.d.ts +18 -0
- package/dist/di-container.d.ts.map +1 -0
- package/dist/di-container.js +43 -0
- package/dist/di-container.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/repositories/manifest.repository.d.ts +26 -0
- package/dist/repositories/manifest.repository.d.ts.map +1 -0
- package/dist/repositories/manifest.repository.js +90 -0
- package/dist/repositories/manifest.repository.js.map +1 -0
- package/dist/repositories/schema.repository.d.ts +30 -0
- package/dist/repositories/schema.repository.d.ts.map +1 -0
- package/dist/repositories/schema.repository.js +143 -0
- package/dist/repositories/schema.repository.js.map +1 -0
- package/dist/services/generation.service.d.ts +54 -0
- package/dist/services/generation.service.d.ts.map +1 -0
- package/dist/services/generation.service.js +298 -0
- package/dist/services/generation.service.js.map +1 -0
- package/dist/services/migration.service.d.ts +30 -0
- package/dist/services/migration.service.d.ts.map +1 -0
- package/dist/services/migration.service.js +231 -0
- package/dist/services/migration.service.js.map +1 -0
- package/dist/services/runtime/openai.adapter.d.ts +94 -0
- package/dist/services/runtime/openai.adapter.d.ts.map +1 -0
- package/dist/services/runtime/openai.adapter.js +209 -0
- package/dist/services/runtime/openai.adapter.js.map +1 -0
- package/dist/services/validation.service.d.ts +45 -0
- package/dist/services/validation.service.d.ts.map +1 -0
- package/dist/services/validation.service.js +362 -0
- package/dist/services/validation.service.js.map +1 -0
- package/dist/services/validators/anthropic.validator.d.ts +9 -0
- package/dist/services/validators/anthropic.validator.d.ts.map +1 -0
- package/dist/services/validators/anthropic.validator.js +105 -0
- package/dist/services/validators/anthropic.validator.js.map +1 -0
- package/dist/services/validators/autogen.validator.d.ts +9 -0
- package/dist/services/validators/autogen.validator.d.ts.map +1 -0
- package/dist/services/validators/autogen.validator.js +111 -0
- package/dist/services/validators/autogen.validator.js.map +1 -0
- package/dist/services/validators/crewai.validator.d.ts +9 -0
- package/dist/services/validators/crewai.validator.d.ts.map +1 -0
- package/dist/services/validators/crewai.validator.js +117 -0
- package/dist/services/validators/crewai.validator.js.map +1 -0
- package/dist/services/validators/cursor.validator.d.ts +9 -0
- package/dist/services/validators/cursor.validator.d.ts.map +1 -0
- package/dist/services/validators/cursor.validator.js +88 -0
- package/dist/services/validators/cursor.validator.js.map +1 -0
- package/dist/services/validators/index.d.ts +15 -0
- package/dist/services/validators/index.d.ts.map +1 -0
- package/dist/services/validators/index.js +15 -0
- package/dist/services/validators/index.js.map +1 -0
- package/dist/services/validators/langchain.validator.d.ts +9 -0
- package/dist/services/validators/langchain.validator.d.ts.map +1 -0
- package/dist/services/validators/langchain.validator.js +103 -0
- package/dist/services/validators/langchain.validator.js.map +1 -0
- package/dist/services/validators/langflow.validator.d.ts +9 -0
- package/dist/services/validators/langflow.validator.d.ts.map +1 -0
- package/dist/services/validators/langflow.validator.js +92 -0
- package/dist/services/validators/langflow.validator.js.map +1 -0
- package/dist/services/validators/langgraph.validator.d.ts +9 -0
- package/dist/services/validators/langgraph.validator.d.ts.map +1 -0
- package/dist/services/validators/langgraph.validator.js +123 -0
- package/dist/services/validators/langgraph.validator.js.map +1 -0
- package/dist/services/validators/llamaindex.validator.d.ts +9 -0
- package/dist/services/validators/llamaindex.validator.d.ts.map +1 -0
- package/dist/services/validators/llamaindex.validator.js +121 -0
- package/dist/services/validators/llamaindex.validator.js.map +1 -0
- package/dist/services/validators/openai.validator.d.ts +9 -0
- package/dist/services/validators/openai.validator.d.ts.map +1 -0
- package/dist/services/validators/openai.validator.js +126 -0
- package/dist/services/validators/openai.validator.js.map +1 -0
- package/dist/services/validators/vercel-ai.validator.d.ts +9 -0
- package/dist/services/validators/vercel-ai.validator.d.ts.map +1 -0
- package/dist/services/validators/vercel-ai.validator.js +99 -0
- package/dist/services/validators/vercel-ai.validator.js.map +1 -0
- package/dist/spec/v0.1.9/agent-autonomous-extensions.json +234 -0
- package/dist/spec/v0.1.9/ecosystem-compliance.json +235 -0
- package/dist/spec/v0.1.9/ossa-v0.1.9.schema.json +695 -0
- package/dist/spec/v0.1.9/ossa-v0.1.9.schema.json.backup +695 -0
- package/dist/spec/v0.1.9/reasoning-compliance.json +654 -0
- package/dist/spec/v0.2.2/kagent-enhancements.json +395 -0
- package/dist/spec/v0.2.2/ossa-0.2.2.schema.json +906 -0
- package/dist/spec/v0.2.2/ossa-0.2.2.yaml +448 -0
- package/dist/spec/v0.2.2/ossa-reasoning-compliance-1.0.schema.json +424 -0
- package/dist/spec/v0.2.3/CHANGELOG.md +176 -0
- package/dist/spec/v0.2.3/README.md +154 -0
- package/dist/spec/v0.2.3/migrations/v0.2.2-to-v0.2.3.md +343 -0
- package/dist/spec/v0.2.3/ossa-0.2.3.schema.json +1397 -0
- package/dist/spec/v0.2.3/ossa-0.2.3.yaml +448 -0
- package/dist/spec/v0.2.4-dev/CHANGELOG.md +403 -0
- package/dist/spec/v0.2.4-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.4-dev/ossa-0.2.4-dev.schema.json +1696 -0
- package/dist/spec/v0.2.4-dev/ossa-0.2.4-dev.yaml +581 -0
- package/dist/spec/v0.2.5-dev/CHANGELOG.md +171 -0
- package/dist/spec/v0.2.5-dev/examples/customer-support-graph.ossa.yaml +362 -0
- package/dist/spec/v0.2.5-dev/examples/parallel-processors.ossa.yaml +464 -0
- package/dist/spec/v0.2.5-dev/examples/research-team.ossa.yaml +440 -0
- package/dist/spec/v0.2.5-dev/migrations/v0.2.4-to-v0.2.5.md +317 -0
- package/dist/spec/v0.2.5-dev/ossa-0.2.5-dev.schema.json +1732 -0
- package/dist/spec/v0.2.5-dev/ossa-0.2.5-dev.yaml +409 -0
- package/dist/types/index.d.ts +178 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/openapi-extensions.d.ts +164 -0
- package/dist/types/openapi-extensions.d.ts.map +1 -0
- package/dist/types/openapi-extensions.js +6 -0
- package/dist/types/openapi-extensions.js.map +1 -0
- package/docs/OSSA-COMPLIANT-BADGE.md +248 -0
- package/docs/README.md +31 -0
- package/docs/VERSIONING.md +284 -0
- package/docs/agent-openapi-spec.yml +942 -0
- package/docs/getting-started.md +87 -0
- package/docs/migration/general-agent-schema.yml +255 -0
- package/docs/migration/migration-manifest.json +64 -0
- package/docs/openapi-extensions.md +930 -0
- package/docs/schemas/openapi-extensions.schema.json +486 -0
- package/examples/adk-integration/code-review-workflow.yml +136 -0
- package/examples/adk-integration/customer-support.yml +263 -0
- package/examples/adk-integration/data-pipeline.yml +173 -0
- package/examples/advanced/patterns/compliance-context-production.json +53 -0
- package/examples/advanced/patterns/model-router.ts +274 -0
- package/examples/advanced/patterns/smart-model-routing.ts +248 -0
- package/examples/advanced/workflows/hybrid-model-strategy.yaml +232 -0
- package/examples/agent-manifests/critics/critic-agent.yaml +149 -0
- package/examples/agent-manifests/governors/governor-agent.yaml +128 -0
- package/examples/agent-manifests/integrators/integrator-agent.yaml +103 -0
- package/examples/agent-manifests/judges/judge-agent.yaml +153 -0
- package/examples/agent-manifests/monitors/monitor-agent.yaml +122 -0
- package/examples/agent-manifests/orchestrators/orchestrator-agent.yaml +247 -0
- package/examples/agent-manifests/sample-compliant-agent.yaml +147 -0
- package/examples/agent-manifests/workers/worker-agent.yaml +82 -0
- package/examples/anthropic/claude-assistant.ossa.json +45 -0
- package/examples/architecture/model-configuration/ollama-integration.ts +110 -0
- package/examples/autogen/multi-agent.ossa.json +37 -0
- package/examples/bridge-configurations.yaml +346 -0
- package/examples/bridges/Dockerfile.production +87 -0
- package/examples/bridges/__pycache__/aiflow-bridge-enhanced.cpython-313.pyc +0 -0
- package/examples/bridges/__pycache__/aiflow-phoenix-tracing.cpython-313.pyc +0 -0
- package/examples/bridges/__pycache__/test_aiflow_integration.cpython-313.pyc +0 -0
- package/examples/bridges/aiflow-bridge-enhanced.py +462 -0
- package/examples/bridges/aiflow-bridge-example.yml +310 -0
- package/examples/bridges/aiflow-phoenix-tracing.py +310 -0
- package/examples/bridges/aiflow-registration-api.openapi.yml +439 -0
- package/examples/bridges/k8s/configmap.yaml +121 -0
- package/examples/bridges/k8s/deployment-simple.yaml +34 -0
- package/examples/bridges/k8s/deployment.yaml +275 -0
- package/examples/bridges/k8s/hpa.yaml +126 -0
- package/examples/bridges/k8s/ingress.yaml +155 -0
- package/examples/bridges/kagent-bridge-example.yml +94 -0
- package/examples/bridges/load-tests/Dockerfile +28 -0
- package/examples/bridges/load-tests/k6-load-test.js +302 -0
- package/examples/bridges/load-tests/requirements.txt +20 -0
- package/examples/bridges/loadtest/k6-scenarios.js +270 -0
- package/examples/bridges/phase4/SLO-SLA.yaml +249 -0
- package/examples/bridges/phase4/chaos-tests.yaml +226 -0
- package/examples/bridges/requirements.txt +24 -0
- package/examples/bridges/test_aiflow_integration.py +341 -0
- package/examples/common_npm/agent-router.ossa.yaml +182 -0
- package/examples/common_npm/agent-router.v0.2.2.ossa.yaml +60 -0
- package/examples/compliance-agent.yml +155 -0
- package/examples/crewai/research-team.ossa.json +36 -0
- package/examples/cursor/code-review-agent.ossa.json +47 -0
- package/examples/drupal/gitlab-ml-recommender.ossa.yaml +609 -0
- package/examples/drupal/gitlab-ml-recommender.v0.2.2.ossa.yaml +68 -0
- package/examples/enterprise/agent.yml +452 -0
- package/examples/extensions/drupal-v1.yml +266 -0
- package/examples/extensions/kagent-v1.yml +167 -0
- package/examples/getting-started/hello-world-complete.ossa.yaml +266 -0
- package/examples/integration-patterns/agent-to-agent-orchestration.ossa.yaml +376 -0
- package/examples/kagent/README.md +31 -0
- package/examples/kagent/compliance-validator.ossa.yaml +111 -0
- package/examples/kagent/cost-optimizer.ossa.yaml +93 -0
- package/examples/kagent/documentation-agent.ossa.yaml +91 -0
- package/examples/kagent/k8s-troubleshooter-v1.ossa.yaml +269 -0
- package/examples/kagent/k8s-troubleshooter-v1.v0.2.2.ossa.yaml +106 -0
- package/examples/kagent/k8s-troubleshooter.ossa.yaml +257 -0
- package/examples/kagent/security-scanner.ossa.yaml +140 -0
- package/examples/langchain/chain-agent.ossa.json +42 -0
- package/examples/langflow/workflow-agent.ossa.json +39 -0
- package/examples/langgraph/state-machine-agent.ossa.json +59 -0
- package/examples/llamaindex/rag-agent.ossa.json +41 -0
- package/examples/migration-guides/from-langchain-to-ossa.yaml +309 -0
- package/examples/minimal/agent.yml +152 -0
- package/examples/minimal/openapi.yaml +95 -0
- package/examples/openai/swarm-agent.ossa.json +59 -0
- package/examples/openapi-extensions/README.md +87 -0
- package/examples/openapi-extensions/minimal-agent-api.openapi.yml +288 -0
- package/examples/openapi-extensions/orchestrator-agent-api.openapi.yml +633 -0
- package/examples/openapi-extensions/worker-agent-api.openapi.yml +533 -0
- package/examples/production/agent.yml +713 -0
- package/examples/production/document-analyzer-openai.yml +134 -0
- package/examples/quickstart/support-agent.ossa.yaml +59 -0
- package/examples/service-registry-usage.ts +423 -0
- package/examples/spec-examples/audit-agent.yml +147 -0
- package/examples/spec-examples/chat-agent.yml +189 -0
- package/examples/spec-examples/compliance-agent.yml +204 -0
- package/examples/spec-examples/data-processing-agent.yml +132 -0
- package/examples/spec-examples/development-agent.yml +138 -0
- package/examples/spec-examples/edge-agent.yml +101 -0
- package/examples/spec-examples/integration-agent.yml +129 -0
- package/examples/spec-examples/monitoring-agent.yml +130 -0
- package/examples/spec-examples/serverless-agent.yml +82 -0
- package/examples/spec-examples/workflow-agent.yml +223 -0
- package/examples/templates/ossa-compliance.yaml +56 -0
- package/examples/typescript/advanced/demo-registry.ts +168 -0
- package/examples/typescript/mcpb-agent-example.ts +358 -0
- package/examples/vercel/edge-agent.ossa.json +43 -0
- package/infrastructure/docker-compose.yml +33 -0
- package/junit.xml +1 -0
- package/openapi/drupal-agent-api.openapi.yaml +348 -0
- package/openapi/gitlab-orchestrator.openapi.yaml +330 -0
- package/openapi/helm-generator.openapi.yaml +389 -0
- package/openapi/ossa-core-api.openapi.yaml +1448 -0
- package/openapi/ossa-registry-api.openapi.yaml +980 -0
- package/openapi/ossa-registry.openapi.yaml +782 -0
- package/openapi/self-evolving-ecosystem.openapi.yaml +1530 -0
- package/openapi/unified-agent-gateway.openapi.yaml +833 -0
- package/ossa-website-swarm-tasks.json +105 -0
- package/package.json +132 -0
- package/release.config.js +64 -0
- package/spec/v0.1.9/agent-autonomous-extensions.json +234 -0
- package/spec/v0.1.9/ecosystem-compliance.json +235 -0
- package/spec/v0.1.9/ossa-v0.1.9.schema.json +695 -0
- package/spec/v0.1.9/ossa-v0.1.9.schema.json.backup +695 -0
- package/spec/v0.1.9/reasoning-compliance.json +654 -0
- package/spec/v0.2.2/kagent-enhancements.json +395 -0
- package/spec/v0.2.2/ossa-0.2.2.schema.json +906 -0
- package/spec/v0.2.2/ossa-0.2.2.yaml +448 -0
- package/spec/v0.2.2/ossa-reasoning-compliance-1.0.schema.json +424 -0
- package/spec/v0.2.3/CHANGELOG.md +176 -0
- package/spec/v0.2.3/README.md +154 -0
- package/spec/v0.2.3/migrations/v0.2.2-to-v0.2.3.md +343 -0
- package/spec/v0.2.3/ossa-0.2.3.schema.json +1397 -0
- package/spec/v0.2.3/ossa-0.2.3.yaml +448 -0
- package/spec/v0.2.4-dev/CHANGELOG.md +403 -0
- package/spec/v0.2.4-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.4-dev/ossa-0.2.4-dev.schema.json +1696 -0
- package/spec/v0.2.4-dev/ossa-0.2.4-dev.yaml +581 -0
- package/spec/v0.2.5-dev/CHANGELOG.md +171 -0
- package/spec/v0.2.5-dev/examples/customer-support-graph.ossa.yaml +362 -0
- package/spec/v0.2.5-dev/examples/parallel-processors.ossa.yaml +464 -0
- package/spec/v0.2.5-dev/examples/research-team.ossa.yaml +440 -0
- package/spec/v0.2.5-dev/migrations/v0.2.4-to-v0.2.5.md +317 -0
- package/spec/v0.2.5-dev/ossa-0.2.5-dev.schema.json +1732 -0
- package/spec/v0.2.5-dev/ossa-0.2.5-dev.yaml +409 -0
- package/test-results.xml +1 -0
- package/website/.lighthouserc.js +20 -0
- package/website/.prettierrc +10 -0
- package/website/Dockerfile +17 -0
- package/website/app/about/page.tsx +295 -0
- package/website/app/api/validate/route.ts +88 -0
- package/website/app/blog/[slug]/page.tsx +167 -0
- package/website/app/blog/page.tsx +162 -0
- package/website/app/docs/[[...slug]]/page.tsx +349 -0
- package/website/app/docs/core-concepts/project-structure/page.tsx +349 -0
- package/website/app/ecosystem/page.tsx +375 -0
- package/website/app/examples/page.tsx +123 -0
- package/website/app/globals.css +108 -0
- package/website/app/layout.tsx +106 -0
- package/website/app/page.tsx +409 -0
- package/website/app/playground/page.tsx +507 -0
- package/website/app/robots.ts +19 -0
- package/website/app/rss.xml/route.ts +74 -0
- package/website/app/schema/page.tsx +970 -0
- package/website/app/sitemap.ts +56 -0
- package/website/app/specification/page.tsx +211 -0
- package/website/components/InstallCommand.tsx +96 -0
- package/website/components/Logo.tsx +24 -0
- package/website/components/StructuredData.tsx +65 -0
- package/website/components/docs/DocsSearch.tsx +104 -0
- package/website/components/docs/DocsSidebar.tsx +118 -0
- package/website/components/docs/MarkdownContent.tsx +183 -0
- package/website/components/docs/VersionSelector.tsx +49 -0
- package/website/components/examples/ExamplesViewer.tsx +293 -0
- package/website/components/layout/Footer.tsx +111 -0
- package/website/components/layout/Header.tsx +170 -0
- package/website/components/schema/SchemaExplorer.tsx +213 -0
- package/website/content/blog/OpenAPI-AI-Agents-Standard.md +285 -0
- package/website/content/blog/Why-Formal-Standards-Matter-Now.md +209 -0
- package/website/content/blog/introducing-ossa-framework.md +328 -0
- package/website/content/blog/ossa-production-results.md +279 -0
- package/website/content/blog/welcome-to-ossa.md +43 -0
- package/website/content/blog/why-ai-agents-need-open-standard.md +98 -0
- package/website/content/docs/00-HOME.md +160 -0
- package/website/content/docs/AIFlow-Framework-Integration-with-OSSA.md +107 -0
- package/website/content/docs/OpenAPI-Extensions.md +498 -0
- package/website/content/docs/architecture/execution-flow.md +335 -0
- package/website/content/docs/architecture/multi-agent-systems.md +737 -0
- package/website/content/docs/architecture/overview.md +121 -0
- package/website/content/docs/architecture/stack-integration.md +461 -0
- package/website/content/docs/changelog.md +246 -0
- package/website/content/docs/contributing.md +599 -0
- package/website/content/docs/core-concepts/project-structure.md +348 -0
- package/website/content/docs/ecosystem/framework-support.md +821 -0
- package/website/content/docs/ecosystem/overview.md +366 -0
- package/website/content/docs/examples/Migration-Guides.md +214 -0
- package/website/content/docs/examples.md +71 -0
- package/website/content/docs/for-audiences/Enterprises.md +256 -0
- package/website/content/docs/for-audiences/Students-Researchers.md +122 -0
- package/website/content/docs/for-audiences/architects.md +224 -0
- package/website/content/docs/for-audiences/developers.md +220 -0
- package/website/content/docs/getting-started/5-minute-overview.md +85 -0
- package/website/content/docs/getting-started/Hello-World.md +184 -0
- package/website/content/docs/getting-started/first-agent.md +196 -0
- package/website/content/docs/getting-started/installation.md +155 -0
- package/website/content/docs/getting-started/running-agents.md +107 -0
- package/website/content/docs/integrations/aiflow.md +104 -0
- package/website/content/docs/integrations/drupal.md +105 -0
- package/website/content/docs/migration-guides/00-index.md +76 -0
- package/website/content/docs/migration-guides/README.md +133 -0
- package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +1750 -0
- package/website/content/docs/migration-guides/crewai-to-ossa.md +274 -0
- package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +2017 -0
- package/website/content/docs/migration-guides/index.md +133 -0
- package/website/content/docs/migration-guides/langchain-to-ossa.md +1714 -0
- package/website/content/docs/migration-guides/langflow-to-ossa.md +2075 -0
- package/website/content/docs/migration-guides/openai-to-ossa.md +1202 -0
- package/website/content/docs/openapi-extensions/examples.md +550 -0
- package/website/content/docs/openapi-extensions/index.md +495 -0
- package/website/content/docs/openapi-extensions/operation-extensions.md +398 -0
- package/website/content/docs/openapi-extensions/root-extensions.md +364 -0
- package/website/content/docs/pre-release/index.md +175 -0
- package/website/content/docs/quick-reference.md +17 -0
- package/website/content/docs/schema-reference/agent-spec.md +406 -0
- package/website/content/docs/schema-reference/autonomy.md +568 -0
- package/website/content/docs/schema-reference/constraints.md +543 -0
- package/website/content/docs/schema-reference/index.md +176 -0
- package/website/content/docs/schema-reference/llm-config.md +445 -0
- package/website/content/docs/schema-reference/observability.md +654 -0
- package/website/content/docs/schema-reference/ossa-manifest.md +309 -0
- package/website/content/docs/schema-reference/taxonomy.md +509 -0
- package/website/content/docs/schema-reference/tools.md +628 -0
- package/website/content/docs/templates/blog-post.md +43 -0
- package/website/content/docs/use-cases/00-index.md +395 -0
- package/website/content/docs/use-cases/cicd-code-review.md +1236 -0
- package/website/content/docs/use-cases/customer-support.md +1234 -0
- package/website/content/docs/use-cases/enterprise-compliance.md +1208 -0
- package/website/content/docs/use-cases/research-multi-agent.md +1161 -0
- package/website/lib/version.ts +18 -0
- package/website/next.config.js +17 -0
- package/website/next.config.ts +16 -0
- package/website/nginx.conf +32 -0
- package/website/package-lock.json +9145 -0
- package/website/package.json +53 -0
- package/website/postcss.config.js +7 -0
- package/website/postcss.config.mjs +9 -0
- package/website/scripts/sync-version.js +44 -0
- package/website/scripts/sync-wiki.ts +261 -0
- package/website/tailwind.config.js +58 -0
- package/website/tailwind.config.ts +65 -0
|
@@ -0,0 +1,1750 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Anthropic MCP to OSSA"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Migration Guide: Extending Anthropic MCP with OSSA
|
|
6
|
+
|
|
7
|
+
**Version:** 1.0
|
|
8
|
+
**Last Updated:** 2025-11-10
|
|
9
|
+
**Status:** Production-Ready
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 📖 Table of Contents
|
|
14
|
+
|
|
15
|
+
1. [Overview](#overview)
|
|
16
|
+
2. [Why Extend MCP with OSSA?](#why-extend-mcp-with-ossa)
|
|
17
|
+
3. [Key Concepts](#key-concepts)
|
|
18
|
+
4. [Migration Strategy](#migration-strategy)
|
|
19
|
+
5. [Example 1: Simple MCP Server → OSSA Agent](#example-1-simple-mcp-server--ossa-agent)
|
|
20
|
+
6. [Example 2: MCP Tools → OSSA Capabilities](#example-2-mcp-tools--ossa-capabilities)
|
|
21
|
+
7. [Example 3: MCP Resources → OSSA Data Sources](#example-3-mcp-resources--ossa-data-sources)
|
|
22
|
+
8. [Integration Patterns](#integration-patterns)
|
|
23
|
+
9. [Best Practices](#best-practices)
|
|
24
|
+
10. [Troubleshooting](#troubleshooting)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Overview
|
|
29
|
+
|
|
30
|
+
This guide helps you **extend** your existing Anthropic Model Context Protocol (MCP) servers with the Open Standards for Scalable Agents (OSSA) specification. OSSA is not a replacement for MCP—it's a **superset** that adds:
|
|
31
|
+
|
|
32
|
+
- **Multi-protocol support** (HTTP, gRPC, WebSocket, A2A)
|
|
33
|
+
- **Production features** (monitoring, metrics, policies, compliance)
|
|
34
|
+
- **OpenAPI integration** for REST API exposure
|
|
35
|
+
- **Agent orchestration** capabilities
|
|
36
|
+
- **Kubernetes deployment** support
|
|
37
|
+
- **Enterprise governance** (encryption, audit, RBAC)
|
|
38
|
+
|
|
39
|
+
**Key Insight:** OSSA agents can **natively speak MCP** while also supporting other protocols. You get MCP compatibility + production-ready infrastructure.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Why Extend MCP with OSSA?
|
|
44
|
+
|
|
45
|
+
### MCP Alone (Good for Claude Desktop)
|
|
46
|
+
|
|
47
|
+
| Feature | MCP Native | Notes |
|
|
48
|
+
|---------|-----------|-------|
|
|
49
|
+
| Claude Desktop Integration | ✅ | Perfect for local use |
|
|
50
|
+
| Stdio Transport | ✅ | Simple, local execution |
|
|
51
|
+
| Tools | ✅ | Function calls |
|
|
52
|
+
| Resources | ✅ | Data access |
|
|
53
|
+
| Prompts | ✅ | Template support |
|
|
54
|
+
| **HTTP/REST API** | ❌ | Limited to MCP protocol |
|
|
55
|
+
| **Kubernetes Deployment** | ❌ | No native support |
|
|
56
|
+
| **Monitoring/Metrics** | ❌ | Manual implementation |
|
|
57
|
+
| **Multi-LLM Support** | ❌ | Claude-specific |
|
|
58
|
+
| **Agent Orchestration** | ❌ | Single-agent only |
|
|
59
|
+
| **Compliance/Audit** | ❌ | No built-in support |
|
|
60
|
+
|
|
61
|
+
### MCP + OSSA (Production-Ready)
|
|
62
|
+
|
|
63
|
+
| Feature | MCP + OSSA | Notes |
|
|
64
|
+
|---------|-----------|-------|
|
|
65
|
+
| Claude Desktop Integration | ✅ | **Full backward compatibility** |
|
|
66
|
+
| Stdio Transport | ✅ | MCP native support |
|
|
67
|
+
| Tools | ✅ | Via MCP bridge |
|
|
68
|
+
| Resources | ✅ | Via MCP bridge |
|
|
69
|
+
| Prompts | ✅ | Via MCP bridge |
|
|
70
|
+
| **HTTP/REST API** | ✅ | OpenAPI-first design |
|
|
71
|
+
| **Kubernetes Deployment** | ✅ | Native YAML manifests |
|
|
72
|
+
| **Monitoring/Metrics** | ✅ | Prometheus, Grafana, traces |
|
|
73
|
+
| **Multi-LLM Support** | ✅ | OpenAI, Anthropic, etc. |
|
|
74
|
+
| **Agent Orchestration** | ✅ | Multi-agent coordination |
|
|
75
|
+
| **Compliance/Audit** | ✅ | ISO42001, SOC2, GDPR |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Key Concepts
|
|
80
|
+
|
|
81
|
+
### MCP → OSSA Mapping
|
|
82
|
+
|
|
83
|
+
| MCP Concept | OSSA Equivalent | Relationship |
|
|
84
|
+
|-------------|----------------|--------------|
|
|
85
|
+
| **MCP Server** | **OSSA Agent** | Agent wraps MCP server functionality |
|
|
86
|
+
| **MCP Tool** | **OSSA Capability** | 1:1 mapping via bridge config |
|
|
87
|
+
| **MCP Resource** | **OSSA Data Source** | Exposed via integration endpoints |
|
|
88
|
+
| **Stdio Transport** | **MCP Bridge (stdio)** | Native MCP protocol support |
|
|
89
|
+
| **Tool Parameters** | **Capability Input Schema** | JSON Schema compatible |
|
|
90
|
+
| **Tool Response** | **Capability Output Schema** | Typed responses |
|
|
91
|
+
| N/A | **OpenAPI Bridge** | REST API exposure |
|
|
92
|
+
| N/A | **Monitoring** | Traces, metrics, logs |
|
|
93
|
+
| N/A | **Policies** | Compliance, encryption, audit |
|
|
94
|
+
|
|
95
|
+
### How OSSA Extends MCP
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
┌────────────────────────────────────────────────────────────┐
|
|
99
|
+
│ OSSA Agent │
|
|
100
|
+
│ │
|
|
101
|
+
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
102
|
+
│ │ │ │ │ │ │ │
|
|
103
|
+
│ │ MCP Bridge │ │ OpenAPI REST │ │ A2A P2P │ │
|
|
104
|
+
│ │ (stdio) │ │ (HTTP) │ │ Protocol │ │
|
|
105
|
+
│ │ │ │ │ │ │ │
|
|
106
|
+
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
|
|
107
|
+
│ │ │ │ │
|
|
108
|
+
│ └──────────────────┼──────────────────┘ │
|
|
109
|
+
│ │ │
|
|
110
|
+
│ ┌─────────▼─────────┐ │
|
|
111
|
+
│ │ │ │
|
|
112
|
+
│ │ Core Runtime │ │
|
|
113
|
+
│ │ (Capabilities) │ │
|
|
114
|
+
│ │ │ │
|
|
115
|
+
│ └─────────┬──────────┘ │
|
|
116
|
+
│ │ │
|
|
117
|
+
│ ┌──────────────────┼──────────────────┐ │
|
|
118
|
+
│ │ │ │ │
|
|
119
|
+
│ ┌──────▼───────┐ ┌──────▼───────┐ ┌──────▼───────┐ │
|
|
120
|
+
│ │ │ │ │ │ │ │
|
|
121
|
+
│ │ Monitoring │ │ Policies │ │ Metrics │ │
|
|
122
|
+
│ │ (Traces) │ │ (Audit) │ │ (Prometheus) │ │
|
|
123
|
+
│ │ │ │ │ │ │ │
|
|
124
|
+
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
125
|
+
│ │
|
|
126
|
+
└────────────────────────────────────────────────────────────┘
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Migration Strategy
|
|
132
|
+
|
|
133
|
+
### Phase 1: Assessment
|
|
134
|
+
|
|
135
|
+
1. **Inventory existing MCP servers**
|
|
136
|
+
```bash
|
|
137
|
+
# List MCP servers in Claude Desktop config
|
|
138
|
+
cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
2. **Document MCP tools and resources**
|
|
142
|
+
```bash
|
|
143
|
+
# For each server, document:
|
|
144
|
+
# - Tool names and signatures
|
|
145
|
+
# - Resource URIs and schemas
|
|
146
|
+
# - Transport type (stdio/sse)
|
|
147
|
+
# - Dependencies
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
3. **Identify production requirements**
|
|
151
|
+
```yaml
|
|
152
|
+
# Questions to answer:
|
|
153
|
+
- Need HTTP API access? → OpenAPI bridge
|
|
154
|
+
- Need Kubernetes deployment? → OSSA runtime config
|
|
155
|
+
- Need monitoring/metrics? → OSSA monitoring
|
|
156
|
+
- Need multi-agent coordination? → OSSA orchestration
|
|
157
|
+
- Need compliance tracking? → OSSA policies
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Phase 2: Create OSSA Agent
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# Interactive agent creation (recommended)
|
|
164
|
+
buildkit agents create --interactive
|
|
165
|
+
|
|
166
|
+
# Or non-interactive with MCP enabled
|
|
167
|
+
buildkit agents create my-agent \
|
|
168
|
+
--type worker \
|
|
169
|
+
--description "My MCP server as OSSA agent" \
|
|
170
|
+
--mcp \
|
|
171
|
+
--mcp-transport stdio \
|
|
172
|
+
--openapi
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Phase 3: Migrate Logic
|
|
176
|
+
|
|
177
|
+
1. **Copy MCP server code** to agent's `src/` directory
|
|
178
|
+
2. **Map MCP tools** to OSSA capabilities in `agent.yml`
|
|
179
|
+
3. **Configure MCP bridge** for stdio transport
|
|
180
|
+
4. **Add OpenAPI spec** for HTTP access (optional)
|
|
181
|
+
5. **Enable monitoring** (traces, metrics, logs)
|
|
182
|
+
|
|
183
|
+
### Phase 4: Test Both Modes
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Test HTTP mode
|
|
187
|
+
cd .agents/my-agent
|
|
188
|
+
npm install && npm run build
|
|
189
|
+
npm start
|
|
190
|
+
curl http://localhost:3000/health
|
|
191
|
+
|
|
192
|
+
# Test MCP mode (stdio)
|
|
193
|
+
MCP_MODE=stdio npm start
|
|
194
|
+
# (Connect from Claude Desktop)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Phase 5: Update Claude Desktop Config
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# Generate updated config
|
|
201
|
+
buildkit mcpb claude-config
|
|
202
|
+
|
|
203
|
+
# Or manually add to claude_desktop_config.json
|
|
204
|
+
{
|
|
205
|
+
"mcpServers": {
|
|
206
|
+
"my-agent": {
|
|
207
|
+
"command": "node",
|
|
208
|
+
"args": ["/path/to/.agents/my-agent/dist/index.js"],
|
|
209
|
+
"env": {
|
|
210
|
+
"MCP_MODE": "stdio"
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Example 1: Simple MCP Server → OSSA Agent
|
|
220
|
+
|
|
221
|
+
### Before: Pure MCP Server
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// simple-mcp-server.ts
|
|
225
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
226
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
227
|
+
import {
|
|
228
|
+
CallToolRequestSchema,
|
|
229
|
+
ListToolsRequestSchema
|
|
230
|
+
} from '@modelcontextprotocol/sdk/types';
|
|
231
|
+
|
|
232
|
+
const server = new Server(
|
|
233
|
+
{
|
|
234
|
+
name: 'simple-server',
|
|
235
|
+
version: '1.0.0',
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
capabilities: {
|
|
239
|
+
tools: {},
|
|
240
|
+
},
|
|
241
|
+
}
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
// List tools
|
|
245
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
246
|
+
return {
|
|
247
|
+
tools: [
|
|
248
|
+
{
|
|
249
|
+
name: 'greet',
|
|
250
|
+
description: 'Greet a user',
|
|
251
|
+
inputSchema: {
|
|
252
|
+
type: 'object',
|
|
253
|
+
properties: {
|
|
254
|
+
name: { type: 'string', description: 'Name to greet' }
|
|
255
|
+
},
|
|
256
|
+
required: ['name']
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
]
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Handle tool calls
|
|
264
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
265
|
+
if (request.params.name === 'greet') {
|
|
266
|
+
const { name } = request.params.arguments as { name: string };
|
|
267
|
+
return {
|
|
268
|
+
content: [
|
|
269
|
+
{
|
|
270
|
+
type: 'text',
|
|
271
|
+
text: `Hello, ${name}!`
|
|
272
|
+
}
|
|
273
|
+
]
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
const transport = new StdioServerTransport();
|
|
280
|
+
server.connect(transport);
|
|
281
|
+
console.log('MCP server running on stdio');
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Usage:**
|
|
285
|
+
```json
|
|
286
|
+
// claude_desktop_config.json
|
|
287
|
+
{
|
|
288
|
+
"mcpServers": {
|
|
289
|
+
"simple-server": {
|
|
290
|
+
"command": "node",
|
|
291
|
+
"args": ["simple-mcp-server.js"]
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
**Limitations:**
|
|
298
|
+
- ❌ No HTTP API
|
|
299
|
+
- ❌ No monitoring
|
|
300
|
+
- ❌ No metrics
|
|
301
|
+
- ❌ No health checks
|
|
302
|
+
- ❌ Manual deployment
|
|
303
|
+
- ❌ No orchestration
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### After: OSSA Agent with MCP Bridge
|
|
308
|
+
|
|
309
|
+
**1. Create OSSA Agent:**
|
|
310
|
+
```bash
|
|
311
|
+
buildkit agents create simple-agent \
|
|
312
|
+
--type worker \
|
|
313
|
+
--description "Simple greeting agent with MCP support" \
|
|
314
|
+
--mcp \
|
|
315
|
+
--openapi
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**2. Agent Manifest (`agent.yml`):**
|
|
319
|
+
```yaml
|
|
320
|
+
ossaVersion: "1.0"
|
|
321
|
+
agent:
|
|
322
|
+
id: simple-agent
|
|
323
|
+
name: simple-agent
|
|
324
|
+
version: 1.0.0
|
|
325
|
+
description: Simple greeting agent with MCP support
|
|
326
|
+
role: workflow
|
|
327
|
+
tags:
|
|
328
|
+
- greeting
|
|
329
|
+
- worker
|
|
330
|
+
- mcp
|
|
331
|
+
|
|
332
|
+
runtime:
|
|
333
|
+
type: local
|
|
334
|
+
command: [node, dist/index.js]
|
|
335
|
+
resources:
|
|
336
|
+
cpu: 500m
|
|
337
|
+
memory: 512Mi
|
|
338
|
+
|
|
339
|
+
capabilities:
|
|
340
|
+
- name: greet
|
|
341
|
+
description: Greet a user by name
|
|
342
|
+
input_schema:
|
|
343
|
+
type: object
|
|
344
|
+
properties:
|
|
345
|
+
name:
|
|
346
|
+
type: string
|
|
347
|
+
description: Name to greet
|
|
348
|
+
required: [name]
|
|
349
|
+
output_schema:
|
|
350
|
+
type: object
|
|
351
|
+
properties:
|
|
352
|
+
message:
|
|
353
|
+
type: string
|
|
354
|
+
|
|
355
|
+
integration:
|
|
356
|
+
protocol: http
|
|
357
|
+
endpoints:
|
|
358
|
+
base_url: http://localhost:3000
|
|
359
|
+
health: /health
|
|
360
|
+
metrics: /metrics
|
|
361
|
+
|
|
362
|
+
monitoring:
|
|
363
|
+
traces: true
|
|
364
|
+
metrics: true
|
|
365
|
+
logs: true
|
|
366
|
+
|
|
367
|
+
policies:
|
|
368
|
+
encryption: true
|
|
369
|
+
audit: true
|
|
370
|
+
|
|
371
|
+
bridge:
|
|
372
|
+
# MCP Bridge for Claude Desktop
|
|
373
|
+
mcp:
|
|
374
|
+
enabled: true
|
|
375
|
+
server_type: stdio
|
|
376
|
+
tools:
|
|
377
|
+
- name: greet
|
|
378
|
+
description: Greet a user by name
|
|
379
|
+
capability: greet
|
|
380
|
+
config:
|
|
381
|
+
max_message_size: 1048576
|
|
382
|
+
timeout_ms: 30000
|
|
383
|
+
retry_count: 3
|
|
384
|
+
|
|
385
|
+
# OpenAPI Bridge for REST API
|
|
386
|
+
openapi:
|
|
387
|
+
enabled: true
|
|
388
|
+
spec_url: ./openapi.yaml
|
|
389
|
+
spec_version: "3.1"
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**3. Agent Implementation (`src/index.ts`):**
|
|
393
|
+
```typescript
|
|
394
|
+
import express from 'express';
|
|
395
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
396
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
397
|
+
import {
|
|
398
|
+
CallToolRequestSchema,
|
|
399
|
+
ListToolsRequestSchema,
|
|
400
|
+
} from '@modelcontextprotocol/sdk/types';
|
|
401
|
+
|
|
402
|
+
const app = express();
|
|
403
|
+
const PORT = process.env.PORT || 3000;
|
|
404
|
+
|
|
405
|
+
app.use(express.json());
|
|
406
|
+
|
|
407
|
+
// ========================================
|
|
408
|
+
// HTTP Mode (OpenAPI REST API)
|
|
409
|
+
// ========================================
|
|
410
|
+
|
|
411
|
+
app.get('/health', (req, res) => {
|
|
412
|
+
res.json({
|
|
413
|
+
status: 'healthy',
|
|
414
|
+
agent: 'simple-agent',
|
|
415
|
+
version: '1.0.0',
|
|
416
|
+
timestamp: new Date().toISOString(),
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
app.get('/metrics', (req, res) => {
|
|
421
|
+
// Prometheus metrics
|
|
422
|
+
res.set('Content-Type', 'text/plain');
|
|
423
|
+
res.send(`
|
|
424
|
+
# HELP simple_agent_requests_total Total requests
|
|
425
|
+
# TYPE simple_agent_requests_total counter
|
|
426
|
+
simple_agent_requests_total 42
|
|
427
|
+
`.trim());
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
// Capability: greet
|
|
431
|
+
app.post('/capabilities/greet', async (req, res) => {
|
|
432
|
+
try {
|
|
433
|
+
const { name } = req.body;
|
|
434
|
+
if (!name) {
|
|
435
|
+
return res.status(400).json({ error: 'name is required' });
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
const result = {
|
|
439
|
+
message: `Hello, ${name}!`,
|
|
440
|
+
timestamp: new Date().toISOString(),
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
res.json(result);
|
|
444
|
+
} catch (error: any) {
|
|
445
|
+
res.status(500).json({ error: error.message });
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// ========================================
|
|
450
|
+
// MCP Mode (stdio transport)
|
|
451
|
+
// ========================================
|
|
452
|
+
|
|
453
|
+
if (process.env.MCP_MODE === 'stdio') {
|
|
454
|
+
const server = new Server(
|
|
455
|
+
{
|
|
456
|
+
name: 'simple-agent',
|
|
457
|
+
version: '1.0.0',
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
capabilities: {
|
|
461
|
+
tools: {},
|
|
462
|
+
},
|
|
463
|
+
}
|
|
464
|
+
);
|
|
465
|
+
|
|
466
|
+
// List available tools
|
|
467
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
468
|
+
return {
|
|
469
|
+
tools: [
|
|
470
|
+
{
|
|
471
|
+
name: 'greet',
|
|
472
|
+
description: 'Greet a user by name',
|
|
473
|
+
inputSchema: {
|
|
474
|
+
type: 'object',
|
|
475
|
+
properties: {
|
|
476
|
+
name: {
|
|
477
|
+
type: 'string',
|
|
478
|
+
description: 'Name to greet'
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
required: ['name'],
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
};
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
// Handle tool calls
|
|
489
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
490
|
+
const toolName = request.params.name;
|
|
491
|
+
|
|
492
|
+
if (toolName === 'greet') {
|
|
493
|
+
const { name } = request.params.arguments as { name: string };
|
|
494
|
+
return {
|
|
495
|
+
content: [
|
|
496
|
+
{
|
|
497
|
+
type: 'text',
|
|
498
|
+
text: JSON.stringify({
|
|
499
|
+
message: `Hello, ${name}!`,
|
|
500
|
+
timestamp: new Date().toISOString(),
|
|
501
|
+
}),
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
throw new Error(`Unknown tool: ${toolName}`);
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
const transport = new StdioServerTransport();
|
|
511
|
+
server.connect(transport);
|
|
512
|
+
console.log('MCP server running on stdio');
|
|
513
|
+
} else {
|
|
514
|
+
// HTTP mode
|
|
515
|
+
app.listen(PORT, () => {
|
|
516
|
+
console.log(`Agent listening on port ${PORT} (HTTP mode)`);
|
|
517
|
+
console.log(`Health: http://localhost:${PORT}/health`);
|
|
518
|
+
console.log(`Metrics: http://localhost:${PORT}/metrics`);
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
**4. OpenAPI Spec (`openapi.yaml`):**
|
|
524
|
+
```yaml
|
|
525
|
+
openapi: 3.1.0
|
|
526
|
+
info:
|
|
527
|
+
title: simple-agent API
|
|
528
|
+
version: 1.0.0
|
|
529
|
+
description: Simple greeting agent with MCP support
|
|
530
|
+
|
|
531
|
+
servers:
|
|
532
|
+
- url: http://localhost:3000
|
|
533
|
+
description: Local development
|
|
534
|
+
|
|
535
|
+
paths:
|
|
536
|
+
/health:
|
|
537
|
+
get:
|
|
538
|
+
summary: Health check
|
|
539
|
+
responses:
|
|
540
|
+
'200':
|
|
541
|
+
description: Agent is healthy
|
|
542
|
+
content:
|
|
543
|
+
application/json:
|
|
544
|
+
schema:
|
|
545
|
+
type: object
|
|
546
|
+
properties:
|
|
547
|
+
status:
|
|
548
|
+
type: string
|
|
549
|
+
agent:
|
|
550
|
+
type: string
|
|
551
|
+
version:
|
|
552
|
+
type: string
|
|
553
|
+
timestamp:
|
|
554
|
+
type: string
|
|
555
|
+
|
|
556
|
+
/capabilities/greet:
|
|
557
|
+
post:
|
|
558
|
+
summary: Greet a user
|
|
559
|
+
requestBody:
|
|
560
|
+
required: true
|
|
561
|
+
content:
|
|
562
|
+
application/json:
|
|
563
|
+
schema:
|
|
564
|
+
type: object
|
|
565
|
+
properties:
|
|
566
|
+
name:
|
|
567
|
+
type: string
|
|
568
|
+
description: Name to greet
|
|
569
|
+
required: [name]
|
|
570
|
+
responses:
|
|
571
|
+
'200':
|
|
572
|
+
description: Greeting response
|
|
573
|
+
content:
|
|
574
|
+
application/json:
|
|
575
|
+
schema:
|
|
576
|
+
type: object
|
|
577
|
+
properties:
|
|
578
|
+
message:
|
|
579
|
+
type: string
|
|
580
|
+
timestamp:
|
|
581
|
+
type: string
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
**Benefits:**
|
|
585
|
+
- ✅ **Claude Desktop works** (MCP stdio mode)
|
|
586
|
+
- ✅ **HTTP API available** (curl, Postman, web apps)
|
|
587
|
+
- ✅ **Health checks** (`/health`)
|
|
588
|
+
- ✅ **Metrics** (`/metrics` for Prometheus)
|
|
589
|
+
- ✅ **OpenAPI spec** (auto-generated docs)
|
|
590
|
+
- ✅ **Monitoring ready** (traces, logs)
|
|
591
|
+
- ✅ **Kubernetes ready** (via OSSA runtime config)
|
|
592
|
+
|
|
593
|
+
**Usage:**
|
|
594
|
+
|
|
595
|
+
```bash
|
|
596
|
+
# HTTP mode
|
|
597
|
+
npm start
|
|
598
|
+
curl -X POST http://localhost:3000/capabilities/greet \
|
|
599
|
+
-H "Content-Type: application/json" \
|
|
600
|
+
-d '{"name": "World"}'
|
|
601
|
+
# → {"message": "Hello, World!", "timestamp": "..."}
|
|
602
|
+
|
|
603
|
+
# MCP mode (Claude Desktop)
|
|
604
|
+
MCP_MODE=stdio npm start
|
|
605
|
+
# → Works in Claude Desktop as before
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Example 2: MCP Tools → OSSA Capabilities
|
|
611
|
+
|
|
612
|
+
### Before: MCP Server with Multiple Tools
|
|
613
|
+
|
|
614
|
+
```typescript
|
|
615
|
+
// filesystem-mcp-server.ts
|
|
616
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
617
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
618
|
+
import {
|
|
619
|
+
CallToolRequestSchema,
|
|
620
|
+
ListToolsRequestSchema
|
|
621
|
+
} from '@modelcontextprotocol/sdk/types';
|
|
622
|
+
import fs from 'fs/promises';
|
|
623
|
+
|
|
624
|
+
const server = new Server(
|
|
625
|
+
{ name: 'filesystem-server', version: '1.0.0' },
|
|
626
|
+
{ capabilities: { tools: {} } }
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
630
|
+
return {
|
|
631
|
+
tools: [
|
|
632
|
+
{
|
|
633
|
+
name: 'read_file',
|
|
634
|
+
description: 'Read a file from disk',
|
|
635
|
+
inputSchema: {
|
|
636
|
+
type: 'object',
|
|
637
|
+
properties: {
|
|
638
|
+
path: { type: 'string', description: 'File path' }
|
|
639
|
+
},
|
|
640
|
+
required: ['path']
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
name: 'write_file',
|
|
645
|
+
description: 'Write content to a file',
|
|
646
|
+
inputSchema: {
|
|
647
|
+
type: 'object',
|
|
648
|
+
properties: {
|
|
649
|
+
path: { type: 'string', description: 'File path' },
|
|
650
|
+
content: { type: 'string', description: 'File content' }
|
|
651
|
+
},
|
|
652
|
+
required: ['path', 'content']
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
name: 'list_directory',
|
|
657
|
+
description: 'List files in a directory',
|
|
658
|
+
inputSchema: {
|
|
659
|
+
type: 'object',
|
|
660
|
+
properties: {
|
|
661
|
+
path: { type: 'string', description: 'Directory path' }
|
|
662
|
+
},
|
|
663
|
+
required: ['path']
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
]
|
|
667
|
+
};
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
671
|
+
const { name, arguments: args } = request.params;
|
|
672
|
+
|
|
673
|
+
switch (name) {
|
|
674
|
+
case 'read_file': {
|
|
675
|
+
const content = await fs.readFile(args.path as string, 'utf-8');
|
|
676
|
+
return {
|
|
677
|
+
content: [{ type: 'text', text: content }]
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
case 'write_file': {
|
|
682
|
+
await fs.writeFile(args.path as string, args.content as string);
|
|
683
|
+
return {
|
|
684
|
+
content: [{ type: 'text', text: 'File written successfully' }]
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
case 'list_directory': {
|
|
689
|
+
const files = await fs.readdir(args.path as string);
|
|
690
|
+
return {
|
|
691
|
+
content: [{ type: 'text', text: JSON.stringify(files) }]
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
default:
|
|
696
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
const transport = new StdioServerTransport();
|
|
701
|
+
server.connect(transport);
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
### After: OSSA Agent with Mapped Capabilities
|
|
707
|
+
|
|
708
|
+
**Agent Manifest (`agent.yml`):**
|
|
709
|
+
```yaml
|
|
710
|
+
ossaVersion: "1.0"
|
|
711
|
+
agent:
|
|
712
|
+
id: filesystem-agent
|
|
713
|
+
name: filesystem-agent
|
|
714
|
+
version: 1.0.0
|
|
715
|
+
description: Filesystem operations agent
|
|
716
|
+
role: workflow
|
|
717
|
+
tags: [filesystem, io, worker]
|
|
718
|
+
|
|
719
|
+
runtime:
|
|
720
|
+
type: local
|
|
721
|
+
command: [node, dist/index.js]
|
|
722
|
+
resources:
|
|
723
|
+
cpu: 500m
|
|
724
|
+
memory: 512Mi
|
|
725
|
+
|
|
726
|
+
capabilities:
|
|
727
|
+
# Capability 1: Read File
|
|
728
|
+
- name: read-file
|
|
729
|
+
description: Read a file from disk
|
|
730
|
+
input_schema:
|
|
731
|
+
type: object
|
|
732
|
+
properties:
|
|
733
|
+
path:
|
|
734
|
+
type: string
|
|
735
|
+
description: File path to read
|
|
736
|
+
required: [path]
|
|
737
|
+
output_schema:
|
|
738
|
+
type: object
|
|
739
|
+
properties:
|
|
740
|
+
content:
|
|
741
|
+
type: string
|
|
742
|
+
size:
|
|
743
|
+
type: number
|
|
744
|
+
|
|
745
|
+
# Capability 2: Write File
|
|
746
|
+
- name: write-file
|
|
747
|
+
description: Write content to a file
|
|
748
|
+
input_schema:
|
|
749
|
+
type: object
|
|
750
|
+
properties:
|
|
751
|
+
path:
|
|
752
|
+
type: string
|
|
753
|
+
description: File path to write
|
|
754
|
+
content:
|
|
755
|
+
type: string
|
|
756
|
+
description: Content to write
|
|
757
|
+
required: [path, content]
|
|
758
|
+
output_schema:
|
|
759
|
+
type: object
|
|
760
|
+
properties:
|
|
761
|
+
success:
|
|
762
|
+
type: boolean
|
|
763
|
+
bytes_written:
|
|
764
|
+
type: number
|
|
765
|
+
|
|
766
|
+
# Capability 3: List Directory
|
|
767
|
+
- name: list-directory
|
|
768
|
+
description: List files in a directory
|
|
769
|
+
input_schema:
|
|
770
|
+
type: object
|
|
771
|
+
properties:
|
|
772
|
+
path:
|
|
773
|
+
type: string
|
|
774
|
+
description: Directory path
|
|
775
|
+
required: [path]
|
|
776
|
+
output_schema:
|
|
777
|
+
type: object
|
|
778
|
+
properties:
|
|
779
|
+
files:
|
|
780
|
+
type: array
|
|
781
|
+
items:
|
|
782
|
+
type: string
|
|
783
|
+
|
|
784
|
+
integration:
|
|
785
|
+
protocol: http
|
|
786
|
+
endpoints:
|
|
787
|
+
base_url: http://localhost:3000
|
|
788
|
+
health: /health
|
|
789
|
+
metrics: /metrics
|
|
790
|
+
|
|
791
|
+
monitoring:
|
|
792
|
+
traces: true
|
|
793
|
+
metrics: true
|
|
794
|
+
logs: true
|
|
795
|
+
|
|
796
|
+
policies:
|
|
797
|
+
encryption: true
|
|
798
|
+
audit: true
|
|
799
|
+
# Filesystem access requires audit logging
|
|
800
|
+
compliance: [SOC2, GDPR]
|
|
801
|
+
|
|
802
|
+
bridge:
|
|
803
|
+
mcp:
|
|
804
|
+
enabled: true
|
|
805
|
+
server_type: stdio
|
|
806
|
+
tools:
|
|
807
|
+
# Map OSSA capabilities to MCP tools
|
|
808
|
+
- name: read_file
|
|
809
|
+
description: Read a file from disk
|
|
810
|
+
capability: read-file
|
|
811
|
+
|
|
812
|
+
- name: write_file
|
|
813
|
+
description: Write content to a file
|
|
814
|
+
capability: write-file
|
|
815
|
+
|
|
816
|
+
- name: list_directory
|
|
817
|
+
description: List files in a directory
|
|
818
|
+
capability: list-directory
|
|
819
|
+
|
|
820
|
+
config:
|
|
821
|
+
max_message_size: 10485760 # 10MB for large files
|
|
822
|
+
timeout_ms: 60000 # 60s for large operations
|
|
823
|
+
retry_count: 3
|
|
824
|
+
|
|
825
|
+
openapi:
|
|
826
|
+
enabled: true
|
|
827
|
+
spec_url: ./openapi.yaml
|
|
828
|
+
spec_version: "3.1"
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Implementation (`src/index.ts`):**
|
|
832
|
+
```typescript
|
|
833
|
+
import express from 'express';
|
|
834
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
835
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
836
|
+
import {
|
|
837
|
+
CallToolRequestSchema,
|
|
838
|
+
ListToolsRequestSchema,
|
|
839
|
+
} from '@modelcontextprotocol/sdk/types';
|
|
840
|
+
import fs from 'fs/promises';
|
|
841
|
+
|
|
842
|
+
const app = express();
|
|
843
|
+
const PORT = process.env.PORT || 3000;
|
|
844
|
+
|
|
845
|
+
app.use(express.json());
|
|
846
|
+
|
|
847
|
+
// ========================================
|
|
848
|
+
// Shared Business Logic
|
|
849
|
+
// ========================================
|
|
850
|
+
|
|
851
|
+
class FilesystemService {
|
|
852
|
+
async readFile(path: string) {
|
|
853
|
+
const content = await fs.readFile(path, 'utf-8');
|
|
854
|
+
const stats = await fs.stat(path);
|
|
855
|
+
return {
|
|
856
|
+
content,
|
|
857
|
+
size: stats.size,
|
|
858
|
+
modified: stats.mtime.toISOString(),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
async writeFile(path: string, content: string) {
|
|
863
|
+
await fs.writeFile(path, content);
|
|
864
|
+
const stats = await fs.stat(path);
|
|
865
|
+
return {
|
|
866
|
+
success: true,
|
|
867
|
+
bytes_written: stats.size,
|
|
868
|
+
path,
|
|
869
|
+
};
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
async listDirectory(path: string) {
|
|
873
|
+
const entries = await fs.readdir(path, { withFileTypes: true });
|
|
874
|
+
return {
|
|
875
|
+
files: entries.map(e => ({
|
|
876
|
+
name: e.name,
|
|
877
|
+
type: e.isDirectory() ? 'directory' : 'file',
|
|
878
|
+
})),
|
|
879
|
+
count: entries.length,
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
const service = new FilesystemService();
|
|
885
|
+
|
|
886
|
+
// ========================================
|
|
887
|
+
// HTTP Mode (OpenAPI REST API)
|
|
888
|
+
// ========================================
|
|
889
|
+
|
|
890
|
+
app.get('/health', (req, res) => {
|
|
891
|
+
res.json({
|
|
892
|
+
status: 'healthy',
|
|
893
|
+
agent: 'filesystem-agent',
|
|
894
|
+
version: '1.0.0',
|
|
895
|
+
});
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
app.post('/capabilities/read-file', async (req, res) => {
|
|
899
|
+
try {
|
|
900
|
+
const { path } = req.body;
|
|
901
|
+
const result = await service.readFile(path);
|
|
902
|
+
res.json(result);
|
|
903
|
+
} catch (error: any) {
|
|
904
|
+
res.status(500).json({ error: error.message });
|
|
905
|
+
}
|
|
906
|
+
});
|
|
907
|
+
|
|
908
|
+
app.post('/capabilities/write-file', async (req, res) => {
|
|
909
|
+
try {
|
|
910
|
+
const { path, content } = req.body;
|
|
911
|
+
const result = await service.writeFile(path, content);
|
|
912
|
+
res.json(result);
|
|
913
|
+
} catch (error: any) {
|
|
914
|
+
res.status(500).json({ error: error.message });
|
|
915
|
+
}
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
app.post('/capabilities/list-directory', async (req, res) => {
|
|
919
|
+
try {
|
|
920
|
+
const { path } = req.body;
|
|
921
|
+
const result = await service.listDirectory(path);
|
|
922
|
+
res.json(result);
|
|
923
|
+
} catch (error: any) {
|
|
924
|
+
res.status(500).json({ error: error.message });
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
|
|
928
|
+
// ========================================
|
|
929
|
+
// MCP Mode (stdio transport)
|
|
930
|
+
// ========================================
|
|
931
|
+
|
|
932
|
+
if (process.env.MCP_MODE === 'stdio') {
|
|
933
|
+
const server = new Server(
|
|
934
|
+
{ name: 'filesystem-agent', version: '1.0.0' },
|
|
935
|
+
{ capabilities: { tools: {} } }
|
|
936
|
+
);
|
|
937
|
+
|
|
938
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
939
|
+
return {
|
|
940
|
+
tools: [
|
|
941
|
+
{
|
|
942
|
+
name: 'read_file',
|
|
943
|
+
description: 'Read a file from disk',
|
|
944
|
+
inputSchema: {
|
|
945
|
+
type: 'object',
|
|
946
|
+
properties: {
|
|
947
|
+
path: { type: 'string', description: 'File path' },
|
|
948
|
+
},
|
|
949
|
+
required: ['path'],
|
|
950
|
+
},
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
name: 'write_file',
|
|
954
|
+
description: 'Write content to a file',
|
|
955
|
+
inputSchema: {
|
|
956
|
+
type: 'object',
|
|
957
|
+
properties: {
|
|
958
|
+
path: { type: 'string', description: 'File path' },
|
|
959
|
+
content: { type: 'string', description: 'Content' },
|
|
960
|
+
},
|
|
961
|
+
required: ['path', 'content'],
|
|
962
|
+
},
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
name: 'list_directory',
|
|
966
|
+
description: 'List files in a directory',
|
|
967
|
+
inputSchema: {
|
|
968
|
+
type: 'object',
|
|
969
|
+
properties: {
|
|
970
|
+
path: { type: 'string', description: 'Directory path' },
|
|
971
|
+
},
|
|
972
|
+
required: ['path'],
|
|
973
|
+
},
|
|
974
|
+
},
|
|
975
|
+
],
|
|
976
|
+
};
|
|
977
|
+
});
|
|
978
|
+
|
|
979
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
980
|
+
const { name, arguments: args } = request.params;
|
|
981
|
+
|
|
982
|
+
try {
|
|
983
|
+
let result;
|
|
984
|
+
|
|
985
|
+
switch (name) {
|
|
986
|
+
case 'read_file':
|
|
987
|
+
result = await service.readFile(args.path as string);
|
|
988
|
+
break;
|
|
989
|
+
|
|
990
|
+
case 'write_file':
|
|
991
|
+
result = await service.writeFile(
|
|
992
|
+
args.path as string,
|
|
993
|
+
args.content as string
|
|
994
|
+
);
|
|
995
|
+
break;
|
|
996
|
+
|
|
997
|
+
case 'list_directory':
|
|
998
|
+
result = await service.listDirectory(args.path as string);
|
|
999
|
+
break;
|
|
1000
|
+
|
|
1001
|
+
default:
|
|
1002
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
return {
|
|
1006
|
+
content: [
|
|
1007
|
+
{
|
|
1008
|
+
type: 'text',
|
|
1009
|
+
text: JSON.stringify(result),
|
|
1010
|
+
},
|
|
1011
|
+
],
|
|
1012
|
+
};
|
|
1013
|
+
} catch (error: any) {
|
|
1014
|
+
return {
|
|
1015
|
+
content: [
|
|
1016
|
+
{
|
|
1017
|
+
type: 'text',
|
|
1018
|
+
text: JSON.stringify({ error: error.message }),
|
|
1019
|
+
},
|
|
1020
|
+
],
|
|
1021
|
+
isError: true,
|
|
1022
|
+
};
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
|
|
1026
|
+
const transport = new StdioServerTransport();
|
|
1027
|
+
server.connect(transport);
|
|
1028
|
+
console.log('MCP server running on stdio');
|
|
1029
|
+
} else {
|
|
1030
|
+
app.listen(PORT, () => {
|
|
1031
|
+
console.log(`Filesystem agent listening on port ${PORT}`);
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
**Key Benefits:**
|
|
1037
|
+
- ✅ **Single codebase** serves both MCP and HTTP
|
|
1038
|
+
- ✅ **Shared business logic** (FilesystemService)
|
|
1039
|
+
- ✅ **OpenAPI docs** auto-generated from schema
|
|
1040
|
+
- ✅ **Audit logging** enabled for compliance
|
|
1041
|
+
- ✅ **Metrics tracking** for filesystem operations
|
|
1042
|
+
- ✅ **Error handling** consistent across protocols
|
|
1043
|
+
|
|
1044
|
+
---
|
|
1045
|
+
|
|
1046
|
+
## Example 3: MCP Resources → OSSA Data Sources
|
|
1047
|
+
|
|
1048
|
+
### Before: MCP Server with Resources
|
|
1049
|
+
|
|
1050
|
+
```typescript
|
|
1051
|
+
// database-mcp-server.ts
|
|
1052
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
1053
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
1054
|
+
import {
|
|
1055
|
+
ListResourcesRequestSchema,
|
|
1056
|
+
ReadResourceRequestSchema
|
|
1057
|
+
} from '@modelcontextprotocol/sdk/types';
|
|
1058
|
+
|
|
1059
|
+
const server = new Server(
|
|
1060
|
+
{ name: 'database-server', version: '1.0.0' },
|
|
1061
|
+
{ capabilities: { resources: {} } }
|
|
1062
|
+
);
|
|
1063
|
+
|
|
1064
|
+
// List available resources
|
|
1065
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1066
|
+
return {
|
|
1067
|
+
resources: [
|
|
1068
|
+
{
|
|
1069
|
+
uri: 'db://users',
|
|
1070
|
+
name: 'Users Table',
|
|
1071
|
+
description: 'All users in the database',
|
|
1072
|
+
mimeType: 'application/json'
|
|
1073
|
+
},
|
|
1074
|
+
{
|
|
1075
|
+
uri: 'db://posts',
|
|
1076
|
+
name: 'Posts Table',
|
|
1077
|
+
description: 'All blog posts',
|
|
1078
|
+
mimeType: 'application/json'
|
|
1079
|
+
}
|
|
1080
|
+
]
|
|
1081
|
+
};
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
// Read a specific resource
|
|
1085
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
1086
|
+
const uri = request.params.uri;
|
|
1087
|
+
|
|
1088
|
+
if (uri === 'db://users') {
|
|
1089
|
+
const users = await fetchUsers(); // Mock DB query
|
|
1090
|
+
return {
|
|
1091
|
+
contents: [
|
|
1092
|
+
{
|
|
1093
|
+
uri,
|
|
1094
|
+
mimeType: 'application/json',
|
|
1095
|
+
text: JSON.stringify(users)
|
|
1096
|
+
}
|
|
1097
|
+
]
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
if (uri === 'db://posts') {
|
|
1102
|
+
const posts = await fetchPosts(); // Mock DB query
|
|
1103
|
+
return {
|
|
1104
|
+
contents: [
|
|
1105
|
+
{
|
|
1106
|
+
uri,
|
|
1107
|
+
mimeType: 'application/json',
|
|
1108
|
+
text: JSON.stringify(posts)
|
|
1109
|
+
}
|
|
1110
|
+
]
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
const transport = new StdioServerTransport();
|
|
1118
|
+
server.connect(transport);
|
|
1119
|
+
```
|
|
1120
|
+
|
|
1121
|
+
---
|
|
1122
|
+
|
|
1123
|
+
### After: OSSA Agent with Data Source Integration
|
|
1124
|
+
|
|
1125
|
+
**Agent Manifest (`agent.yml`):**
|
|
1126
|
+
```yaml
|
|
1127
|
+
ossaVersion: "1.0"
|
|
1128
|
+
agent:
|
|
1129
|
+
id: database-agent
|
|
1130
|
+
name: database-agent
|
|
1131
|
+
version: 1.0.0
|
|
1132
|
+
description: Database access agent with MCP resources
|
|
1133
|
+
role: workflow
|
|
1134
|
+
tags: [database, data-source, worker]
|
|
1135
|
+
|
|
1136
|
+
runtime:
|
|
1137
|
+
type: local
|
|
1138
|
+
command: [node, dist/index.js]
|
|
1139
|
+
environment:
|
|
1140
|
+
DATABASE_URL: postgresql://localhost:5432/mydb
|
|
1141
|
+
resources:
|
|
1142
|
+
cpu: 1000m
|
|
1143
|
+
memory: 1Gi
|
|
1144
|
+
|
|
1145
|
+
capabilities:
|
|
1146
|
+
- name: query-users
|
|
1147
|
+
description: Query users table
|
|
1148
|
+
input_schema:
|
|
1149
|
+
type: object
|
|
1150
|
+
properties:
|
|
1151
|
+
filter:
|
|
1152
|
+
type: object
|
|
1153
|
+
limit:
|
|
1154
|
+
type: number
|
|
1155
|
+
default: 100
|
|
1156
|
+
output_schema:
|
|
1157
|
+
type: object
|
|
1158
|
+
properties:
|
|
1159
|
+
users:
|
|
1160
|
+
type: array
|
|
1161
|
+
items:
|
|
1162
|
+
type: object
|
|
1163
|
+
|
|
1164
|
+
- name: query-posts
|
|
1165
|
+
description: Query posts table
|
|
1166
|
+
input_schema:
|
|
1167
|
+
type: object
|
|
1168
|
+
properties:
|
|
1169
|
+
author_id:
|
|
1170
|
+
type: string
|
|
1171
|
+
limit:
|
|
1172
|
+
type: number
|
|
1173
|
+
default: 50
|
|
1174
|
+
output_schema:
|
|
1175
|
+
type: object
|
|
1176
|
+
properties:
|
|
1177
|
+
posts:
|
|
1178
|
+
type: array
|
|
1179
|
+
items:
|
|
1180
|
+
type: object
|
|
1181
|
+
|
|
1182
|
+
integration:
|
|
1183
|
+
protocol: http
|
|
1184
|
+
endpoints:
|
|
1185
|
+
base_url: http://localhost:3000
|
|
1186
|
+
health: /health
|
|
1187
|
+
metrics: /metrics
|
|
1188
|
+
# Data source endpoints
|
|
1189
|
+
data_sources:
|
|
1190
|
+
- uri: /data/users
|
|
1191
|
+
description: Users table resource
|
|
1192
|
+
- uri: /data/posts
|
|
1193
|
+
description: Posts table resource
|
|
1194
|
+
|
|
1195
|
+
monitoring:
|
|
1196
|
+
traces: true
|
|
1197
|
+
metrics: true
|
|
1198
|
+
logs: true
|
|
1199
|
+
alerts:
|
|
1200
|
+
- name: slow_query
|
|
1201
|
+
condition: query_duration_ms > 1000
|
|
1202
|
+
severity: warning
|
|
1203
|
+
|
|
1204
|
+
policies:
|
|
1205
|
+
encryption: true
|
|
1206
|
+
audit: true
|
|
1207
|
+
compliance: [SOC2, GDPR, HIPAA]
|
|
1208
|
+
# Database access requires strict compliance
|
|
1209
|
+
data_retention_days: 90
|
|
1210
|
+
rate_limits:
|
|
1211
|
+
- endpoint: /data/*
|
|
1212
|
+
max_requests_per_minute: 100
|
|
1213
|
+
|
|
1214
|
+
bridge:
|
|
1215
|
+
mcp:
|
|
1216
|
+
enabled: true
|
|
1217
|
+
server_type: stdio
|
|
1218
|
+
# Map resources to OSSA capabilities
|
|
1219
|
+
resources:
|
|
1220
|
+
- uri: db://users
|
|
1221
|
+
name: Users Table
|
|
1222
|
+
description: All users in the database
|
|
1223
|
+
capability: query-users
|
|
1224
|
+
|
|
1225
|
+
- uri: db://posts
|
|
1226
|
+
name: Posts Table
|
|
1227
|
+
description: All blog posts
|
|
1228
|
+
capability: query-posts
|
|
1229
|
+
|
|
1230
|
+
config:
|
|
1231
|
+
max_message_size: 10485760 # 10MB for large datasets
|
|
1232
|
+
timeout_ms: 30000
|
|
1233
|
+
retry_count: 3
|
|
1234
|
+
|
|
1235
|
+
openapi:
|
|
1236
|
+
enabled: true
|
|
1237
|
+
spec_url: ./openapi.yaml
|
|
1238
|
+
spec_version: "3.1"
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
**Implementation (`src/index.ts`):**
|
|
1242
|
+
```typescript
|
|
1243
|
+
import express from 'express';
|
|
1244
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
1245
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
1246
|
+
import {
|
|
1247
|
+
ListResourcesRequestSchema,
|
|
1248
|
+
ReadResourceRequestSchema,
|
|
1249
|
+
} from '@modelcontextprotocol/sdk/types';
|
|
1250
|
+
|
|
1251
|
+
const app = express();
|
|
1252
|
+
const PORT = process.env.PORT || 3000;
|
|
1253
|
+
|
|
1254
|
+
app.use(express.json());
|
|
1255
|
+
|
|
1256
|
+
// ========================================
|
|
1257
|
+
// Database Service (Shared Logic)
|
|
1258
|
+
// ========================================
|
|
1259
|
+
|
|
1260
|
+
class DatabaseService {
|
|
1261
|
+
async queryUsers(filter?: any, limit: number = 100) {
|
|
1262
|
+
// Mock implementation - replace with real DB query
|
|
1263
|
+
const users = [
|
|
1264
|
+
{ id: 1, name: 'Alice', email: 'alice@example.com' },
|
|
1265
|
+
{ id: 2, name: 'Bob', email: 'bob@example.com' },
|
|
1266
|
+
];
|
|
1267
|
+
return {
|
|
1268
|
+
users: users.slice(0, limit),
|
|
1269
|
+
count: users.length,
|
|
1270
|
+
timestamp: new Date().toISOString(),
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
async queryPosts(authorId?: string, limit: number = 50) {
|
|
1275
|
+
// Mock implementation - replace with real DB query
|
|
1276
|
+
const posts = [
|
|
1277
|
+
{ id: 1, title: 'Hello World', author_id: '1' },
|
|
1278
|
+
{ id: 2, title: 'OSSA Guide', author_id: '1' },
|
|
1279
|
+
];
|
|
1280
|
+
return {
|
|
1281
|
+
posts: posts.slice(0, limit),
|
|
1282
|
+
count: posts.length,
|
|
1283
|
+
timestamp: new Date().toISOString(),
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
const db = new DatabaseService();
|
|
1289
|
+
|
|
1290
|
+
// ========================================
|
|
1291
|
+
// HTTP Mode (OpenAPI REST API)
|
|
1292
|
+
// ========================================
|
|
1293
|
+
|
|
1294
|
+
app.get('/health', (req, res) => {
|
|
1295
|
+
res.json({
|
|
1296
|
+
status: 'healthy',
|
|
1297
|
+
agent: 'database-agent',
|
|
1298
|
+
version: '1.0.0',
|
|
1299
|
+
database: 'connected',
|
|
1300
|
+
});
|
|
1301
|
+
});
|
|
1302
|
+
|
|
1303
|
+
app.get('/metrics', (req, res) => {
|
|
1304
|
+
res.set('Content-Type', 'text/plain');
|
|
1305
|
+
res.send(`
|
|
1306
|
+
# HELP db_queries_total Total database queries
|
|
1307
|
+
# TYPE db_queries_total counter
|
|
1308
|
+
db_queries_total{table="users"} 1234
|
|
1309
|
+
db_queries_total{table="posts"} 567
|
|
1310
|
+
`.trim());
|
|
1311
|
+
});
|
|
1312
|
+
|
|
1313
|
+
// Data source endpoints (RESTful resources)
|
|
1314
|
+
app.get('/data/users', async (req, res) => {
|
|
1315
|
+
try {
|
|
1316
|
+
const limit = parseInt(req.query.limit as string) || 100;
|
|
1317
|
+
const result = await db.queryUsers({}, limit);
|
|
1318
|
+
res.json(result);
|
|
1319
|
+
} catch (error: any) {
|
|
1320
|
+
res.status(500).json({ error: error.message });
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
app.get('/data/posts', async (req, res) => {
|
|
1325
|
+
try {
|
|
1326
|
+
const authorId = req.query.author_id as string;
|
|
1327
|
+
const limit = parseInt(req.query.limit as string) || 50;
|
|
1328
|
+
const result = await db.queryPosts(authorId, limit);
|
|
1329
|
+
res.json(result);
|
|
1330
|
+
} catch (error: any) {
|
|
1331
|
+
res.status(500).json({ error: error.message });
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1334
|
+
|
|
1335
|
+
// Capability endpoints
|
|
1336
|
+
app.post('/capabilities/query-users', async (req, res) => {
|
|
1337
|
+
try {
|
|
1338
|
+
const { filter, limit } = req.body;
|
|
1339
|
+
const result = await db.queryUsers(filter, limit);
|
|
1340
|
+
res.json(result);
|
|
1341
|
+
} catch (error: any) {
|
|
1342
|
+
res.status(500).json({ error: error.message });
|
|
1343
|
+
}
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
app.post('/capabilities/query-posts', async (req, res) => {
|
|
1347
|
+
try {
|
|
1348
|
+
const { author_id, limit } = req.body;
|
|
1349
|
+
const result = await db.queryPosts(author_id, limit);
|
|
1350
|
+
res.json(result);
|
|
1351
|
+
} catch (error: any) {
|
|
1352
|
+
res.status(500).json({ error: error.message });
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
|
|
1356
|
+
// ========================================
|
|
1357
|
+
// MCP Mode (stdio transport)
|
|
1358
|
+
// ========================================
|
|
1359
|
+
|
|
1360
|
+
if (process.env.MCP_MODE === 'stdio') {
|
|
1361
|
+
const server = new Server(
|
|
1362
|
+
{ name: 'database-agent', version: '1.0.0' },
|
|
1363
|
+
{ capabilities: { resources: {} } }
|
|
1364
|
+
);
|
|
1365
|
+
|
|
1366
|
+
// List resources
|
|
1367
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
1368
|
+
return {
|
|
1369
|
+
resources: [
|
|
1370
|
+
{
|
|
1371
|
+
uri: 'db://users',
|
|
1372
|
+
name: 'Users Table',
|
|
1373
|
+
description: 'All users in the database',
|
|
1374
|
+
mimeType: 'application/json',
|
|
1375
|
+
},
|
|
1376
|
+
{
|
|
1377
|
+
uri: 'db://posts',
|
|
1378
|
+
name: 'Posts Table',
|
|
1379
|
+
description: 'All blog posts',
|
|
1380
|
+
mimeType: 'application/json',
|
|
1381
|
+
},
|
|
1382
|
+
],
|
|
1383
|
+
};
|
|
1384
|
+
});
|
|
1385
|
+
|
|
1386
|
+
// Read resource
|
|
1387
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
1388
|
+
const { uri } = request.params;
|
|
1389
|
+
|
|
1390
|
+
try {
|
|
1391
|
+
let data;
|
|
1392
|
+
|
|
1393
|
+
if (uri === 'db://users') {
|
|
1394
|
+
data = await db.queryUsers();
|
|
1395
|
+
} else if (uri === 'db://posts') {
|
|
1396
|
+
data = await db.queryPosts();
|
|
1397
|
+
} else {
|
|
1398
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
return {
|
|
1402
|
+
contents: [
|
|
1403
|
+
{
|
|
1404
|
+
uri,
|
|
1405
|
+
mimeType: 'application/json',
|
|
1406
|
+
text: JSON.stringify(data),
|
|
1407
|
+
},
|
|
1408
|
+
],
|
|
1409
|
+
};
|
|
1410
|
+
} catch (error: any) {
|
|
1411
|
+
throw new Error(`Failed to read resource ${uri}: ${error.message}`);
|
|
1412
|
+
}
|
|
1413
|
+
});
|
|
1414
|
+
|
|
1415
|
+
const transport = new StdioServerTransport();
|
|
1416
|
+
server.connect(transport);
|
|
1417
|
+
console.log('MCP server running on stdio');
|
|
1418
|
+
} else {
|
|
1419
|
+
app.listen(PORT, () => {
|
|
1420
|
+
console.log(`Database agent listening on port ${PORT}`);
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
```
|
|
1424
|
+
|
|
1425
|
+
**Key Benefits:**
|
|
1426
|
+
- ✅ **MCP resources** mapped to REST endpoints
|
|
1427
|
+
- ✅ **Data source discovery** via OpenAPI
|
|
1428
|
+
- ✅ **Query metrics** tracked (Prometheus)
|
|
1429
|
+
- ✅ **Rate limiting** for data access
|
|
1430
|
+
- ✅ **Compliance tracking** (GDPR, HIPAA)
|
|
1431
|
+
- ✅ **Audit logs** for all queries
|
|
1432
|
+
|
|
1433
|
+
---
|
|
1434
|
+
|
|
1435
|
+
## Integration Patterns
|
|
1436
|
+
|
|
1437
|
+
### Pattern 1: Hybrid Access (MCP + HTTP)
|
|
1438
|
+
|
|
1439
|
+
**Use Case:** Tool accessible from both Claude Desktop and web applications.
|
|
1440
|
+
|
|
1441
|
+
```yaml
|
|
1442
|
+
# agent.yml
|
|
1443
|
+
bridge:
|
|
1444
|
+
mcp:
|
|
1445
|
+
enabled: true
|
|
1446
|
+
server_type: stdio
|
|
1447
|
+
openapi:
|
|
1448
|
+
enabled: true
|
|
1449
|
+
spec_url: ./openapi.yaml
|
|
1450
|
+
```
|
|
1451
|
+
|
|
1452
|
+
**Benefits:**
|
|
1453
|
+
- Claude Desktop users get native MCP experience
|
|
1454
|
+
- Web apps can use REST API
|
|
1455
|
+
- Single agent, dual protocols
|
|
1456
|
+
|
|
1457
|
+
---
|
|
1458
|
+
|
|
1459
|
+
### Pattern 2: Agent Orchestration
|
|
1460
|
+
|
|
1461
|
+
**Use Case:** OSSA orchestrator coordinates multiple MCP agents.
|
|
1462
|
+
|
|
1463
|
+
```yaml
|
|
1464
|
+
# orchestrator-agent.yml
|
|
1465
|
+
ossaVersion: "1.0"
|
|
1466
|
+
agent:
|
|
1467
|
+
id: orchestrator
|
|
1468
|
+
role: orchestration
|
|
1469
|
+
|
|
1470
|
+
capabilities:
|
|
1471
|
+
- name: coordinate-workflow
|
|
1472
|
+
description: Orchestrate multiple agents
|
|
1473
|
+
input_schema:
|
|
1474
|
+
type: object
|
|
1475
|
+
properties:
|
|
1476
|
+
agents:
|
|
1477
|
+
type: array
|
|
1478
|
+
items:
|
|
1479
|
+
type: string
|
|
1480
|
+
|
|
1481
|
+
bridge:
|
|
1482
|
+
# Orchestrator doesn't need MCP
|
|
1483
|
+
# It coordinates other agents via OSSA A2A protocol
|
|
1484
|
+
a2a:
|
|
1485
|
+
enabled: true
|
|
1486
|
+
discovery:
|
|
1487
|
+
mode: registry
|
|
1488
|
+
registry_url: http://localhost:8080
|
|
1489
|
+
```
|
|
1490
|
+
|
|
1491
|
+
**Workflow:**
|
|
1492
|
+
1. Orchestrator receives task via HTTP
|
|
1493
|
+
2. Discovers available agents (some MCP-enabled)
|
|
1494
|
+
3. Coordinates execution via A2A protocol
|
|
1495
|
+
4. Aggregates results
|
|
1496
|
+
|
|
1497
|
+
---
|
|
1498
|
+
|
|
1499
|
+
### Pattern 3: MCP Server Gateway
|
|
1500
|
+
|
|
1501
|
+
**Use Case:** Single OSSA agent exposes multiple MCP servers.
|
|
1502
|
+
|
|
1503
|
+
```yaml
|
|
1504
|
+
# gateway-agent.yml
|
|
1505
|
+
ossaVersion: "1.0"
|
|
1506
|
+
agent:
|
|
1507
|
+
id: mcp-gateway
|
|
1508
|
+
role: workflow
|
|
1509
|
+
|
|
1510
|
+
capabilities:
|
|
1511
|
+
- name: route-to-mcp
|
|
1512
|
+
description: Route requests to appropriate MCP server
|
|
1513
|
+
input_schema:
|
|
1514
|
+
type: object
|
|
1515
|
+
properties:
|
|
1516
|
+
server:
|
|
1517
|
+
type: string
|
|
1518
|
+
enum: [filesystem, database, git]
|
|
1519
|
+
operation:
|
|
1520
|
+
type: string
|
|
1521
|
+
|
|
1522
|
+
bridge:
|
|
1523
|
+
mcp:
|
|
1524
|
+
enabled: true
|
|
1525
|
+
server_type: stdio
|
|
1526
|
+
# Multiple MCP backends
|
|
1527
|
+
upstreams:
|
|
1528
|
+
- name: filesystem
|
|
1529
|
+
command: [node, mcp-filesystem.js]
|
|
1530
|
+
- name: database
|
|
1531
|
+
command: [node, mcp-database.js]
|
|
1532
|
+
- name: git
|
|
1533
|
+
command: [node, mcp-git.js]
|
|
1534
|
+
```
|
|
1535
|
+
|
|
1536
|
+
---
|
|
1537
|
+
|
|
1538
|
+
## Best Practices
|
|
1539
|
+
|
|
1540
|
+
### 1. **Keep MCP Code Portable**
|
|
1541
|
+
|
|
1542
|
+
```typescript
|
|
1543
|
+
// ✅ GOOD: Shared service layer
|
|
1544
|
+
class FilesystemService {
|
|
1545
|
+
async readFile(path: string) {
|
|
1546
|
+
// Business logic here
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
// Use in both HTTP and MCP modes
|
|
1551
|
+
const service = new FilesystemService();
|
|
1552
|
+
```
|
|
1553
|
+
|
|
1554
|
+
### 2. **Use Environment Variables for Mode Selection**
|
|
1555
|
+
|
|
1556
|
+
```typescript
|
|
1557
|
+
// ✅ GOOD: Single entry point, mode-aware
|
|
1558
|
+
if (process.env.MCP_MODE === 'stdio') {
|
|
1559
|
+
startMcpServer();
|
|
1560
|
+
} else {
|
|
1561
|
+
startHttpServer();
|
|
1562
|
+
}
|
|
1563
|
+
```
|
|
1564
|
+
|
|
1565
|
+
### 3. **Map Tool Names Consistently**
|
|
1566
|
+
|
|
1567
|
+
```yaml
|
|
1568
|
+
# agent.yml
|
|
1569
|
+
capabilities:
|
|
1570
|
+
- name: read-file # Kebab-case in OSSA
|
|
1571
|
+
|
|
1572
|
+
bridge:
|
|
1573
|
+
mcp:
|
|
1574
|
+
tools:
|
|
1575
|
+
- name: read_file # Snake_case in MCP
|
|
1576
|
+
capability: read-file # Maps to OSSA
|
|
1577
|
+
```
|
|
1578
|
+
|
|
1579
|
+
### 4. **Enable Monitoring**
|
|
1580
|
+
|
|
1581
|
+
```yaml
|
|
1582
|
+
monitoring:
|
|
1583
|
+
traces: true # OpenTelemetry traces
|
|
1584
|
+
metrics: true # Prometheus metrics
|
|
1585
|
+
logs: true # Structured logging
|
|
1586
|
+
```
|
|
1587
|
+
|
|
1588
|
+
### 5. **Document Both Protocols**
|
|
1589
|
+
|
|
1590
|
+
```yaml
|
|
1591
|
+
metadata:
|
|
1592
|
+
documentation_url: https://docs.example.com/agent
|
|
1593
|
+
# Include both MCP and OpenAPI docs
|
|
1594
|
+
```
|
|
1595
|
+
|
|
1596
|
+
### 6. **Use JSON Schema for Validation**
|
|
1597
|
+
|
|
1598
|
+
```yaml
|
|
1599
|
+
capabilities:
|
|
1600
|
+
- name: greet
|
|
1601
|
+
input_schema:
|
|
1602
|
+
type: object
|
|
1603
|
+
properties:
|
|
1604
|
+
name:
|
|
1605
|
+
type: string
|
|
1606
|
+
minLength: 1
|
|
1607
|
+
required: [name]
|
|
1608
|
+
```
|
|
1609
|
+
|
|
1610
|
+
### 7. **Test Both Modes**
|
|
1611
|
+
|
|
1612
|
+
```bash
|
|
1613
|
+
# Test HTTP mode
|
|
1614
|
+
npm start
|
|
1615
|
+
curl http://localhost:3000/health
|
|
1616
|
+
|
|
1617
|
+
# Test MCP mode
|
|
1618
|
+
MCP_MODE=stdio npm start
|
|
1619
|
+
# Connect from Claude Desktop
|
|
1620
|
+
```
|
|
1621
|
+
|
|
1622
|
+
---
|
|
1623
|
+
|
|
1624
|
+
## Troubleshooting
|
|
1625
|
+
|
|
1626
|
+
### Issue: MCP tools not showing in Claude Desktop
|
|
1627
|
+
|
|
1628
|
+
**Solution:**
|
|
1629
|
+
1. Verify `bridge.mcp.enabled: true` in `agent.yml`
|
|
1630
|
+
2. Check `server_type: stdio`
|
|
1631
|
+
3. Ensure `MCP_MODE=stdio` environment variable
|
|
1632
|
+
4. Restart Claude Desktop
|
|
1633
|
+
5. Check logs: `~/Library/Logs/Claude/`
|
|
1634
|
+
|
|
1635
|
+
```bash
|
|
1636
|
+
# Debug
|
|
1637
|
+
MCP_MODE=stdio node dist/index.js
|
|
1638
|
+
# Should output: "MCP server running on stdio"
|
|
1639
|
+
```
|
|
1640
|
+
|
|
1641
|
+
---
|
|
1642
|
+
|
|
1643
|
+
### Issue: HTTP endpoints return 404
|
|
1644
|
+
|
|
1645
|
+
**Solution:**
|
|
1646
|
+
1. Verify agent is running in HTTP mode (not stdio)
|
|
1647
|
+
2. Check `integration.endpoints.base_url` in `agent.yml`
|
|
1648
|
+
3. Ensure Express routes match capability names
|
|
1649
|
+
|
|
1650
|
+
```bash
|
|
1651
|
+
# Start in HTTP mode
|
|
1652
|
+
npm start # (no MCP_MODE env var)
|
|
1653
|
+
|
|
1654
|
+
# Test
|
|
1655
|
+
curl http://localhost:3000/health
|
|
1656
|
+
```
|
|
1657
|
+
|
|
1658
|
+
---
|
|
1659
|
+
|
|
1660
|
+
### Issue: Tools work in HTTP but not MCP
|
|
1661
|
+
|
|
1662
|
+
**Solution:**
|
|
1663
|
+
1. Check tool name mapping (snake_case in MCP)
|
|
1664
|
+
2. Verify `CallToolRequestSchema` handler
|
|
1665
|
+
3. Ensure JSON response format:
|
|
1666
|
+
|
|
1667
|
+
```typescript
|
|
1668
|
+
return {
|
|
1669
|
+
content: [
|
|
1670
|
+
{
|
|
1671
|
+
type: 'text',
|
|
1672
|
+
text: JSON.stringify(result) // Must be stringified
|
|
1673
|
+
}
|
|
1674
|
+
]
|
|
1675
|
+
};
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
---
|
|
1679
|
+
|
|
1680
|
+
### Issue: Large payloads fail in MCP mode
|
|
1681
|
+
|
|
1682
|
+
**Solution:**
|
|
1683
|
+
Increase `max_message_size` in bridge config:
|
|
1684
|
+
|
|
1685
|
+
```yaml
|
|
1686
|
+
bridge:
|
|
1687
|
+
mcp:
|
|
1688
|
+
config:
|
|
1689
|
+
max_message_size: 10485760 # 10MB (default: 1MB)
|
|
1690
|
+
```
|
|
1691
|
+
|
|
1692
|
+
---
|
|
1693
|
+
|
|
1694
|
+
### Issue: Metrics not showing in Prometheus
|
|
1695
|
+
|
|
1696
|
+
**Solution:**
|
|
1697
|
+
1. Ensure `/metrics` endpoint exists
|
|
1698
|
+
2. Use `text/plain` content type
|
|
1699
|
+
3. Follow Prometheus format:
|
|
1700
|
+
|
|
1701
|
+
```typescript
|
|
1702
|
+
app.get('/metrics', (req, res) => {
|
|
1703
|
+
res.set('Content-Type', 'text/plain');
|
|
1704
|
+
res.send(`
|
|
1705
|
+
# HELP my_metric_total Total count
|
|
1706
|
+
# TYPE my_metric_total counter
|
|
1707
|
+
my_metric_total 123
|
|
1708
|
+
`.trim());
|
|
1709
|
+
});
|
|
1710
|
+
```
|
|
1711
|
+
|
|
1712
|
+
---
|
|
1713
|
+
|
|
1714
|
+
## Summary
|
|
1715
|
+
|
|
1716
|
+
| Aspect | MCP Alone | MCP + OSSA |
|
|
1717
|
+
|--------|-----------|-----------|
|
|
1718
|
+
| **Claude Desktop** | ✅ Native | ✅ Native (via bridge) |
|
|
1719
|
+
| **HTTP API** | ❌ Manual | ✅ Auto-generated |
|
|
1720
|
+
| **Monitoring** | ❌ Manual | ✅ Built-in |
|
|
1721
|
+
| **Orchestration** | ❌ N/A | ✅ Multi-agent |
|
|
1722
|
+
| **Compliance** | ❌ Manual | ✅ Policy-driven |
|
|
1723
|
+
| **Kubernetes** | ❌ Manual | ✅ Native support |
|
|
1724
|
+
| **OpenAPI Docs** | ❌ N/A | ✅ Auto-generated |
|
|
1725
|
+
| **Metrics** | ❌ Manual | ✅ Prometheus-ready |
|
|
1726
|
+
|
|
1727
|
+
**Next Steps:**
|
|
1728
|
+
|
|
1729
|
+
1. **Assess** your existing MCP servers
|
|
1730
|
+
2. **Create** OSSA agents with MCP bridges
|
|
1731
|
+
3. **Migrate** business logic to shared services
|
|
1732
|
+
4. **Test** both MCP (stdio) and HTTP modes
|
|
1733
|
+
5. **Deploy** with monitoring enabled
|
|
1734
|
+
6. **Monitor** metrics and traces
|
|
1735
|
+
7. **Scale** with Kubernetes (optional)
|
|
1736
|
+
|
|
1737
|
+
---
|
|
1738
|
+
|
|
1739
|
+
**Resources:**
|
|
1740
|
+
|
|
1741
|
+
- **OSSA Specification:** [OSSA Complete Agent Reference](/Users/flux423/Sites/LLM/agent-buildkit/docs/architecture/OSSA_COMPLETE_AGENT_REFERENCE.md)
|
|
1742
|
+
- **MCP Protocol:** https://modelcontextprotocol.io
|
|
1743
|
+
- **BuildKit Commands:** `buildkit agents --help`
|
|
1744
|
+
- **MCPB Quickstart:** [MCPB Quickstart Guide](/Users/flux423/Sites/LLM/agent-buildkit/docs/architecture/MCPB_QUICKSTART.md)
|
|
1745
|
+
|
|
1746
|
+
---
|
|
1747
|
+
|
|
1748
|
+
**Version:** 1.0
|
|
1749
|
+
**Maintained By:** Agent BuildKit Team
|
|
1750
|
+
**License:** MIT
|