@polymorphism-tech/morph-spec 8.33.0 → 8.35.0
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/CLAUDE.md +22 -2
- package/README.md +2 -2
- package/bin/morph-spec.js +43 -5
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +5 -4
- package/docs/QUICKSTART.md +1 -1
- package/framework/CLAUDE.md +2 -2
- package/framework/MORPH.md +20 -22
- package/framework/agents.json +198 -44
- package/framework/ai-pin.json +22 -0
- package/framework/commands/morph-media.md +45 -0
- package/framework/docs/CLI.md +238 -10
- package/framework/evals/proof-rubrics/README.md +76 -0
- package/framework/evals/proof-rubrics/eval-de-modelo.md +64 -0
- package/framework/evals/proof-rubrics/fiacao.md +54 -0
- package/framework/evals/proof-rubrics/guard-cego.md +52 -0
- package/framework/evals/proof-rubrics/media-claims.md +109 -0
- package/framework/evals/proof-rubrics/mutation-proof.md +77 -0
- package/framework/evals/proof-rubrics/observabilidade-genai.md +119 -0
- package/framework/evals/proof-rubrics/verde-nao-e-coberto.md +48 -0
- package/framework/evals/rubrics/architecture.md +30 -0
- package/framework/evals/rubrics/code-quality.md +26 -0
- package/framework/evals/rubrics/test-coverage.md +20 -0
- package/framework/hooks/README.md +11 -1
- package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +5 -8
- package/framework/hooks/claude-code/core/block-raw-worktree-add.js +79 -0
- package/framework/hooks/claude-code/core/chain.js +27 -7
- package/framework/hooks/claude-code/core/protect-spec-files.js +41 -4
- package/framework/hooks/claude-code/core/worktree-context.js +83 -14
- package/framework/hooks/claude-code/core/worktree-create.js +206 -0
- package/framework/hooks/claude-code/core/worktree-env-inject.js +87 -0
- package/framework/hooks/claude-code/core/worktree-remove.js +81 -0
- package/framework/hooks/shared/command-tokens.js +23 -0
- package/framework/hooks/shared/e2e-check.js +0 -0
- package/framework/hooks/shared/git-paths.js +25 -0
- package/framework/hooks/shared/hook-response.js +17 -0
- package/framework/hooks/shared/morph-cli.js +134 -0
- package/framework/rules/ai-agents-standards.md +14 -2
- package/framework/rules/infrastructure-standards.md +3 -1
- package/framework/schemas/ai-pin.schema.json +97 -0
- package/framework/schemas/config.schema.json +107 -0
- package/framework/schemas/feature.schema.json +23 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +28 -7
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +2 -2
- package/framework/skills/core/morph-implement/SKILL.md +20 -2
- package/framework/skills/core/morph-media/SKILL.md +215 -0
- package/framework/skills/core/morph-plan/SKILL.md +38 -4
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +166 -9
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/PROVENANCE.json +81 -3
- package/framework/standards/STANDARDS.json +1504 -830
- package/framework/standards/ai-agents/agent-archetypes.md +160 -0
- package/framework/standards/ai-agents/agent-session.md +256 -160
- package/framework/standards/ai-agents/agent-spec.md +196 -0
- package/framework/standards/ai-agents/batching.md +217 -193
- package/framework/standards/ai-agents/context-providers.md +261 -188
- package/framework/standards/ai-agents/conversational-agent-with-phases.md +239 -0
- package/framework/standards/ai-agents/cost-and-budget.md +256 -0
- package/framework/standards/ai-agents/durable-workflows-hitl.md +98 -5
- package/framework/standards/ai-agents/evals-with-cache.md +289 -0
- package/framework/standards/ai-agents/guardrails.md +222 -0
- package/framework/standards/ai-agents/llm-runtime-defaults.md +226 -0
- package/framework/standards/ai-agents/mcp-server.md +351 -250
- package/framework/standards/ai-agents/mcp-tools.md +250 -197
- package/framework/standards/ai-agents/media-pipeline.md +352 -0
- package/framework/standards/ai-agents/media-video.md +267 -0
- package/framework/standards/ai-agents/middleware-patterns.md +241 -207
- package/framework/standards/ai-agents/modalities-image-gen.md +422 -173
- package/framework/standards/ai-agents/modalities-speech-to-text.md +177 -171
- package/framework/standards/ai-agents/modalities-text-to-speech.md +189 -181
- package/framework/standards/ai-agents/modalities-vision.md +205 -201
- package/framework/standards/ai-agents/multi-agent-patterns.md +211 -155
- package/framework/standards/ai-agents/observability-patterns.md +227 -17
- package/framework/standards/ai-agents/production.md +260 -231
- package/framework/standards/ai-agents/prompt-sources.md +389 -0
- package/framework/standards/ai-agents/providers/model-registry.md +293 -158
- package/framework/standards/ai-agents/rag-custom-pgvector.md +69 -4
- package/framework/standards/ai-agents/service-tier-flex.md +143 -135
- package/framework/standards/ai-agents/setup.md +166 -50
- package/framework/standards/ai-agents/structured-output.md +280 -249
- package/framework/standards/ai-agents/sweet-spot.md +129 -109
- package/framework/standards/ai-agents/testing-ai.md +236 -0
- package/framework/standards/ai-agents/vector-data-extensions.md +50 -20
- package/framework/standards/ai-agents/workflows.md +27 -7
- package/framework/standards/frontend/design-system/ai-image-generation.md +12 -0
- package/framework/standards/frontend/design-system/ai-video-generation.md +13 -0
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +90 -0
- package/framework/templates/REGISTRY.json +14 -1
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
- package/framework/templates/dotnet/ai-kit/Directory.Build.props +25 -0
- package/framework/templates/dotnet/ai-kit/Directory.Packages.props +26 -0
- package/framework/templates/dotnet/ai-kit/Morph.AiKit.sln +56 -0
- package/framework/templates/dotnet/ai-kit/NuGet.config +12 -0
- package/framework/templates/dotnet/ai-kit/README.md +128 -0
- package/framework/templates/dotnet/ai-kit/global.json +9 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +65 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +289 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +91 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +91 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +181 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +14 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +174 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +54 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +75 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +71 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +246 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +57 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +78 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +225 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +463 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +32 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +49 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +214 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +168 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +142 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +349 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +42 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +77 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +28 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +107 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +253 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +103 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +259 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +21 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +47 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +102 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +44 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +192 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +94 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +99 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +97 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +133 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +93 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +112 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +288 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +158 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +29 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +208 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +95 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Morph.AiKit.csproj +38 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +119 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +82 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +33 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +267 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +474 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/model-registry.v2.json +87 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +169 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +49 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +495 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +260 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +405 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +379 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +197 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +139 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +157 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +178 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +153 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +194 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +86 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +213 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +95 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +225 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +215 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +33 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +89 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +55 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +60 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +131 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +133 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +127 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +216 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +264 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +148 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +184 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +89 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +98 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +451 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +76 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +33 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +261 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +374 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/.morph-eval-cache.json +12 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/orcamento/acme/a-resposta-estruturada.json +24 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/a-saudacao.json +23 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/b-escalonamento.json +24 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/globex/a-saudacao.json +23 -0
- package/framework/templates/infrastructure/docker/docker-compose.template.yml +24 -14
- package/package.json +3 -3
- package/src/commands/e2e/e2e.js +91 -40
- package/src/commands/project/doctor.js +143 -6
- package/src/commands/project/env.js +95 -0
- package/src/commands/project/update.js +469 -153
- package/src/commands/project/worktree.js +274 -53
- package/src/commands/state/advance.js +24 -2
- package/src/commands/state/approve.js +33 -1
- package/src/commands/state/create.js +72 -11
- package/src/commands/state/delete.js +8 -0
- package/src/commands/state/finish.js +360 -53
- package/src/commands/state/gate-check.js +190 -6
- package/src/commands/state/score.js +36 -1
- package/src/commands/validation/verify.js +134 -25
- package/src/core/state/state-manager.js +9 -1
- package/src/dashboard/app/pages/HookInspector.jsx +430 -418
- package/src/dashboard/scanner/hooks-scanner.js +5 -1
- package/src/lib/ai/ai-checks.js +182 -0
- package/src/lib/ai/ai-project-scan.js +347 -0
- package/src/lib/ai/code-audit.js +181 -0
- package/src/lib/ai/comment-stripper.js +184 -0
- package/src/lib/ai/pin-drift.js +138 -0
- package/src/lib/ai/registry-audit.js +285 -0
- package/src/lib/e2e/compose-env.js +55 -14
- package/src/lib/e2e/stack-teardown.js +115 -0
- package/src/lib/evaluator-report.js +269 -15
- package/src/lib/generators/architecture-scanner.js +2 -1
- package/src/lib/git/default-branch.js +92 -4
- package/src/lib/graph/graphifyignore.js +2 -1
- package/src/lib/installers/effects.js +193 -0
- package/src/lib/installers/templates-reconcile.js +3 -3
- package/src/lib/risk-detector.js +284 -0
- package/src/lib/standards/verified-against.js +276 -0
- package/src/lib/tasks/eval-node.js +485 -0
- package/src/lib/tasks/linux-runner.js +297 -0
- package/src/lib/tasks/test-nodes.js +486 -0
- package/src/lib/tasks/test-runner.js +431 -37
- package/src/lib/validators/verify-runner.js +590 -28
- package/src/lib/worktree/dirs.js +32 -0
- package/src/lib/worktree/docker-audit.js +287 -0
- package/src/lib/worktree/env-allocator.js +69 -11
- package/src/lib/worktree/worktree-audit.js +70 -3
- package/src/scripts/setup-infra.js +24 -11
- package/src/utils/agents-installer.js +18 -8
- package/src/utils/claude-md-injector.js +10 -5
- package/src/utils/file-copier.js +28 -16
- package/src/utils/hooks-installer.js +75 -29
- package/src/utils/skills-installer.js +194 -187
- package/src/utils/version-checker.js +68 -3
- package/framework/standards/ai-agents/prompts-in-db.md +0 -214
|
@@ -1,250 +1,351 @@
|
|
|
1
|
-
# MCP Server — Exposing project capabilities as MCP
|
|
2
|
-
|
|
3
|
-
> **Scope:** stacks=["dotnet"]
|
|
4
|
-
> **Layer:** 2 (on-keyword)
|
|
5
|
-
> **Keywords:** mcp server, expose mcp, build mcp server, mcp host, publish tools, McpServerTool, AddMcpServer
|
|
6
|
-
> **Read by Claude in:** implement (quando um projeto expõe capacidades como MCP server para consumo externo)
|
|
7
|
-
|
|
8
|
-
**Verified against:**
|
|
9
|
-
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
## Quando criar um MCP server
|
|
13
|
-
|
|
14
|
-
Crie um MCP server quando você quer **expor capacidades do projeto** de forma padronizada para **agentes ou ferramentas externas** consumirem. O protocolo MCP garante interoperabilidade: qualquer agente compatível (Claude Code, outro agent MAF, VS Code Copilot, etc.) pode descobrir e usar as tools do servidor.
|
|
15
|
-
|
|
16
|
-
**Crie um MCP server quando:**
|
|
17
|
-
|
|
18
|
-
- Claude Code (ou outro agente externo) precisa executar queries/ações neste projeto
|
|
19
|
-
- Outro projeto MAF precisa consumir lógica encapsulada aqui via protocolo padrão
|
|
20
|
-
- Você quer expor capacidades de negócio de forma descobrível via `ListTools`
|
|
21
|
-
- O projeto é um serviço de infraestrutura que deve ser consumível cross-framework
|
|
22
|
-
|
|
23
|
-
**NÃO crie um MCP server quando:**
|
|
24
|
-
|
|
25
|
-
- As tools são usadas apenas pelos agentes do próprio projeto → use tools nativas `[Description]`
|
|
26
|
-
- É uma lógica de um único endpoint interno → `AIFunctionFactory.Create()` é suficiente
|
|
27
|
-
- A integração é ponto-a-ponto com um único consumidor → DI direta ou A2A é mais simples
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## A API
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
-
|
|
244
|
-
- `
|
|
245
|
-
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
1
|
+
# MCP Server — Exposing project capabilities as MCP
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 2 (on-keyword)
|
|
5
|
+
> **Keywords:** mcp server, expose mcp, build mcp server, mcp host, publish tools, McpServerTool, AddMcpServer, request filters, stateless, spec 2026-07-28
|
|
6
|
+
> **Read by Claude in:** implement (quando um projeto expõe capacidades como MCP server para consumo externo)
|
|
7
|
+
|
|
8
|
+
**Verified against:** ModelContextProtocol 2.2.0 + ModelContextProtocol.AspNetCore 2.2.0 (ai-pin 2026-09-08; o `.AspNetCore` não está no pin — versão apurada no nuget.org em 2026-09-08) + revisão de spec MCP **2026-07-28** (modelcontextprotocol.io/specification/versioning, lido 2026-09-08). **Verificação documental — o ai-kit não exercita MCP**, e por isso este standard NÃO carimba `provado por`. Os nomes de tipo, os defaults e os avisos de obsolescência abaixo foram **medidos por reflexão sobre as assemblies 2.2.0** em 2026-09-08. Last-verified: 2026-09-08.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Quando criar um MCP server
|
|
13
|
+
|
|
14
|
+
Crie um MCP server quando você quer **expor capacidades do projeto** de forma padronizada para **agentes ou ferramentas externas** consumirem. O protocolo MCP garante interoperabilidade: qualquer agente compatível (Claude Code, outro agent MAF, VS Code Copilot, etc.) pode descobrir e usar as tools do servidor.
|
|
15
|
+
|
|
16
|
+
**Crie um MCP server quando:**
|
|
17
|
+
|
|
18
|
+
- Claude Code (ou outro agente externo) precisa executar queries/ações neste projeto
|
|
19
|
+
- Outro projeto MAF precisa consumir lógica encapsulada aqui via protocolo padrão
|
|
20
|
+
- Você quer expor capacidades de negócio de forma descobrível via `ListTools`
|
|
21
|
+
- O projeto é um serviço de infraestrutura que deve ser consumível cross-framework
|
|
22
|
+
|
|
23
|
+
**NÃO crie um MCP server quando:**
|
|
24
|
+
|
|
25
|
+
- As tools são usadas apenas pelos agentes do próprio projeto → use tools nativas `[Description]`
|
|
26
|
+
- É uma lógica de um único endpoint interno → `AIFunctionFactory.Create()` é suficiente
|
|
27
|
+
- A integração é ponto-a-ponto com um único consumidor → DI direta ou A2A é mais simples
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## A API
|
|
32
|
+
|
|
33
|
+
### Não existe "MCP 2.0" como revisão de especificação
|
|
34
|
+
|
|
35
|
+
A confusão vale ser desfeita antes de qualquer código, porque ela muda o que se procura na documentação:
|
|
36
|
+
|
|
37
|
+
| Coisa | Como é versionada | Valor corrente (2026-09-08) |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **A especificação MCP** | por **data** | revisão **`2026-07-28`** (sucede `2025-11-25`) |
|
|
40
|
+
| **O SDK C# `ModelContextProtocol`** | SemVer | **2.2.0**, publicado 2026-08-13 |
|
|
41
|
+
|
|
42
|
+
"MCP 2.0" é a **major do SDK**, nunca uma revisão de spec. Fonte: modelcontextprotocol.io/specification/versioning e o changelog da revisão `2026-07-28`, lidos em 2026-09-08.
|
|
43
|
+
|
|
44
|
+
### O que a revisão `2026-07-28` mudou para quem escreve servidor
|
|
45
|
+
|
|
46
|
+
- **Sessões removidas** — o cabeçalho `Mcp-Session-Id` deixou de existir (**SEP-2567**).
|
|
47
|
+
- **`initialize` / `notifications/initialized` removidos** — versão e capacidades viajam em `_meta` **por request** (**SEP-2575**).
|
|
48
|
+
- Novo RPC **`server/discover`**.
|
|
49
|
+
- **`ping`, `logging/setLevel` e `notifications/roots/list_changed` removidos.**
|
|
50
|
+
- **Roots, Sampling e Logging deprecados** (**SEP-2577**).
|
|
51
|
+
- **Tasks** (long-running) saíram do core para a extensão `io.modelcontextprotocol/tasks`.
|
|
52
|
+
- **Elicitation/sampling substituídos por MRTR** — `InputRequiredResult` + `InputRequest.ForElicitation(...)` (**SEP-2322**).
|
|
53
|
+
- **Resultado cacheável** — `ICacheableResult` com `TimeToLive` e `CacheScope` (**SEP-2549**).
|
|
54
|
+
- **HTTP+SSE formalmente Deprecated** (Streamable HTTP é o transporte).
|
|
55
|
+
|
|
56
|
+
> **Duas dessas afirmações não dependem do changelog: elas estão gravadas na assembly.** Medido em `ModelContextProtocol.AspNetCore` 2.2.0 e `ModelContextProtocol.Core` 2.2.0, no texto do `[Obsolete]` de cada membro:
|
|
57
|
+
> - `HttpServerTransportOptions.EventStreamStore`/`IdleTimeout`/`MaxIdleSessionCount`/`PerSessionExecutionContext`/`SessionMigrationHandler` — *"Stateful Streamable HTTP mode is a back-compat-only escape hatch for 2025-11-25 protocol revision clients and earlier. Set `HttpServerTransportOptions.SessionMode = HttpServerSessionMode.Stateless` (**the default as of the 2026-07-28 protocol revision**) for new code. See SEP-2567."*
|
|
58
|
+
> - `McpServerOptions.MaxSamplingOutputTokens` — *"The Sampling feature is deprecated as of specification version 2026-07-28 … See SEP-2577."*
|
|
59
|
+
> - `HttpServerTransportOptions.EnableLegacySse` — obsoleto: *"…Use Streamable HTTP instead."*
|
|
60
|
+
|
|
61
|
+
### A API C# de servidor NÃO mudou de nome
|
|
62
|
+
|
|
63
|
+
`AddMcpServer()`, `WithStdioServerTransport()`, `WithHttpTransport(...)`, `WithToolsFromAssembly()`, `WithTools([...])`, `[McpServerToolType]`, `[McpServerTool]`, `McpServerTool.Create(...)` e `app.MapMcp()` continuam iguais. **O que mudou é o default**, não a grafia.
|
|
64
|
+
|
|
65
|
+
**Packages:**
|
|
66
|
+
|
|
67
|
+
```xml
|
|
68
|
+
<!-- SDK cliente+servidor do protocolo MCP — no ai-pin.json -->
|
|
69
|
+
<PackageReference Include="ModelContextProtocol" Version="2.2.0" />
|
|
70
|
+
|
|
71
|
+
<!-- Pacote base MAF (para AsAIAgent, AsAIFunction) — no ai-pin.json -->
|
|
72
|
+
<PackageReference Include="Microsoft.Agents.AI" Version="1.20.0" />
|
|
73
|
+
|
|
74
|
+
<!-- Apenas se o transporte for HTTP (server-side).
|
|
75
|
+
NÃO está no ai-pin.json; versão apurada no nuget.org em 2026-09-08. -->
|
|
76
|
+
<PackageReference Include="ModelContextProtocol.AspNetCore" Version="2.2.0" />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Stateless é o DEFAULT, não uma escolha
|
|
80
|
+
|
|
81
|
+
Medido em `ModelContextProtocol.AspNetCore` 2.2.0, instanciando `HttpServerTransportOptions` e lendo os valores iniciais: **`SessionMode == HttpServerSessionMode.Stateless`** e `Stateless == true`. Os valores de `HttpServerSessionMode` são `Stateless` (0), `Stateful` (1) e `StatefulForInitializeClients` (2).
|
|
82
|
+
|
|
83
|
+
Escrever `o.Stateless = true` hoje é redundante; escrever `o.SessionMode = HttpServerSessionMode.Stateful` é **optar por um escape hatch de compatibilidade** com clientes da revisão `2025-11-25` e anteriores — e é isso que a mensagem de obsolescência diz. A versão anterior deste standard apresentava stateless como uma decisão de escala do autor; o protocolo já a tomou.
|
|
84
|
+
|
|
85
|
+
**Dois jeitos de declarar tools:**
|
|
86
|
+
|
|
87
|
+
| Padrão | Quando usar |
|
|
88
|
+
|--------|-------------|
|
|
89
|
+
| Atributos `[McpServerToolType]` + `[McpServerTool]` | Tools são métodos do projeto — padrão canônico do SDK. Descoberta automática via `WithToolsFromAssembly()`. |
|
|
90
|
+
| `McpServerTool.Create(...)` | Embrulhar um agente MAF (`agent.AsAIFunction()`) ou um `AIFunction` construído em runtime como tool. |
|
|
91
|
+
|
|
92
|
+
**Padrão de servidor (stdio):**
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Tools ([McpServerTool] ou McpServerTool.Create)
|
|
96
|
+
→ services.AddMcpServer() // registra o servidor
|
|
97
|
+
→ .WithStdioServerTransport() // transporte: stdio (Claude Code, subprocesso)
|
|
98
|
+
→ .WithToolsFromAssembly() // descobre [McpServerTool] no assembly
|
|
99
|
+
ou .WithTools([tool]) // registra tools criadas em runtime
|
|
100
|
+
→ Host.Build().RunAsync() // sobe o servidor
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Transport stdio** é o padrão para servidores locais (subprocessos, Claude Code tools). **HTTP server-side** usa o pacote `ModelContextProtocol.AspNetCore`: troque `WithStdioServerTransport()` por `WithHttpTransport()` e exponha o endpoint com `app.MapMcp()` num `WebApplication`.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Exemplo C# — tools por atributo (stdio)
|
|
108
|
+
|
|
109
|
+
Padrão canônico: tools são métodos estáticos decorados, descobertos por assembly.
|
|
110
|
+
|
|
111
|
+
```csharp
|
|
112
|
+
using System.ComponentModel;
|
|
113
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
114
|
+
using Microsoft.Extensions.Hosting;
|
|
115
|
+
using ModelContextProtocol.Server;
|
|
116
|
+
|
|
117
|
+
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
|
118
|
+
|
|
119
|
+
builder.Services
|
|
120
|
+
.AddMcpServer()
|
|
121
|
+
.WithStdioServerTransport() // stdio: Claude Code / subprocesso
|
|
122
|
+
.WithToolsFromAssembly(); // descobre [McpServerToolType] neste assembly
|
|
123
|
+
|
|
124
|
+
await builder.Build().RunAsync();
|
|
125
|
+
|
|
126
|
+
// ─── Tool exposta via atributo ──────────────────────────────────────────────
|
|
127
|
+
[McpServerToolType]
|
|
128
|
+
public static class OrderTools
|
|
129
|
+
{
|
|
130
|
+
[McpServerTool, Description("Returns the current status of an order given its ID")]
|
|
131
|
+
public static async Task<string> GetOrderStatus(
|
|
132
|
+
[Description("The order identifier")] string orderId,
|
|
133
|
+
CancellationToken ct)
|
|
134
|
+
{
|
|
135
|
+
// Validação de input antes de qualquer I/O — ver seção Segurança
|
|
136
|
+
if (string.IsNullOrWhiteSpace(orderId) || orderId.Length > 36)
|
|
137
|
+
return "Error: invalid orderId format.";
|
|
138
|
+
|
|
139
|
+
// lógica real do projeto aqui
|
|
140
|
+
return $"Order {orderId}: Confirmed";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
> Tools por atributo podem ser instância (não-estáticas) — nesse caso o tipo é resolvido via DI,
|
|
146
|
+
> permitindo injetar repositories/serviços no construtor. Métodos estáticos são o caso mais simples.
|
|
147
|
+
|
|
148
|
+
## Exemplo C# — agente MAF como tool (runtime)
|
|
149
|
+
|
|
150
|
+
Quando a tool é um agente MAF, use `McpServerTool.Create` com `agent.AsAIFunction()`:
|
|
151
|
+
|
|
152
|
+
```csharp
|
|
153
|
+
using Microsoft.Agents.AI;
|
|
154
|
+
using Microsoft.Extensions.AI;
|
|
155
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
156
|
+
using Microsoft.Extensions.Hosting;
|
|
157
|
+
using ModelContextProtocol.Server;
|
|
158
|
+
|
|
159
|
+
// _modelRegistry vem de ModelRegistry injetado (ai-agents-providers-model-registry)
|
|
160
|
+
AIAgent queryAgent = _modelRegistry.GetChatClient("text-default")
|
|
161
|
+
.AsAIAgent(
|
|
162
|
+
instructions: "You answer questions about project data using the available tools.",
|
|
163
|
+
name: "ProjectQueryAgent");
|
|
164
|
+
|
|
165
|
+
McpServerTool agentTool = McpServerTool.Create(queryAgent.AsAIFunction());
|
|
166
|
+
|
|
167
|
+
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
|
168
|
+
|
|
169
|
+
builder.Services
|
|
170
|
+
.AddMcpServer()
|
|
171
|
+
.WithStdioServerTransport()
|
|
172
|
+
.WithTools([agentTool]); // tool criada em runtime → WithTools, não WithToolsFromAssembly
|
|
173
|
+
|
|
174
|
+
await builder.Build().RunAsync();
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Exemplo C# — transport HTTP
|
|
178
|
+
|
|
179
|
+
Para expor o MCP server via HTTP (consumível pela rede), use `ModelContextProtocol.AspNetCore`:
|
|
180
|
+
|
|
181
|
+
```csharp
|
|
182
|
+
using ModelContextProtocol.Server;
|
|
183
|
+
|
|
184
|
+
var builder = WebApplication.CreateBuilder(args);
|
|
185
|
+
|
|
186
|
+
builder.Services
|
|
187
|
+
.AddMcpServer()
|
|
188
|
+
.WithHttpTransport() // SessionMode = Stateless já é o default (medido em 2.2.0)
|
|
189
|
+
.WithToolsFromAssembly();
|
|
190
|
+
|
|
191
|
+
var app = builder.Build();
|
|
192
|
+
|
|
193
|
+
app.MapMcp(); // expõe o endpoint MCP (Streamable HTTP)
|
|
194
|
+
app.Run();
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
> Não escreva `options.Stateless = true`: é redundante desde a revisão `2026-07-28`. Se você
|
|
198
|
+
> precisar de `SessionMode = HttpServerSessionMode.Stateful`, saiba que está optando por um
|
|
199
|
+
> **escape hatch de compatibilidade** com clientes antigos — o próprio SDK diz isso no
|
|
200
|
+
> `[Obsolete]`. Para HTTP em produção, proteja `MapMcp()` com autenticação — ver seção Segurança.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Filtros de request — listar não é poder chamar
|
|
205
|
+
|
|
206
|
+
Este é o mecanismo que permite **um servidor MCP servir vários tenants** sem um processo por tenant. A API foi medida em `ModelContextProtocol` 2.2.0 (`McpRequestFilterBuilderExtensions`) e `ModelContextProtocol.AspNetCore` 2.2.0 (`HttpMcpServerBuilderExtensions`).
|
|
207
|
+
|
|
208
|
+
```csharp
|
|
209
|
+
services.AddMcpServer()
|
|
210
|
+
.WithListToolsHandler(async (context, ct) => new ListToolsResult { Tools = GetTools() })
|
|
211
|
+
.WithRequestFilters(f =>
|
|
212
|
+
{
|
|
213
|
+
// (1) Poda a LISTAGEM — o cliente não vê a tool.
|
|
214
|
+
f.AddListToolsFilter(next => async (context, ct) =>
|
|
215
|
+
{
|
|
216
|
+
var result = await next(context, ct);
|
|
217
|
+
result.Tools = [.. result.Tools.Where(t => AllowedFor(context.User, t))];
|
|
218
|
+
return result;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// (2) Bloqueia a CHAMADA — sem isto, quem souber o nome chama assim mesmo.
|
|
222
|
+
f.AddCallToolFilter(next => async (context, ct) =>
|
|
223
|
+
{
|
|
224
|
+
if (!AllowedFor(context.User, context.Params!.Name)) // ClaimsPrincipal por request
|
|
225
|
+
throw new McpException("tool not available for this principal");
|
|
226
|
+
return await next(context, ct);
|
|
227
|
+
});
|
|
228
|
+
})
|
|
229
|
+
.AddAuthorizationFilters(); // a ORDEM importa — ver abaixo
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Duas regras que este standard existe para gravar:**
|
|
233
|
+
|
|
234
|
+
1. **São DOIS filtros, não um.** `AddListToolsFilter` **esconde** a tool; só `AddCallToolFilter` **impede chamá-la**. Um cliente que já conhece o nome — porque leu a lista antes, porque outro tenant tem a mesma tool, ou porque adivinhou — chama direto. Poda de listagem é ergonomia, não autorização.
|
|
235
|
+
2. **Cliente já conectado não relê a lista até reconectar.** Revogar acesso podando a listagem não revoga nada para quem já está dentro. A revogação real é o filtro de `CallTool`.
|
|
236
|
+
|
|
237
|
+
**A ordem do encadeamento é semântica:** um filtro registrado **antes** de `AddAuthorizationFilters()` roda com a lista **completa** — vê todas as tools, inclusive as que a autorização removeria. Se a intenção é filtrar o que já passou pela autorização, registre depois.
|
|
238
|
+
|
|
239
|
+
Filtros disponíveis (medidos): `AddListToolsFilter`, `AddCallToolFilter`, `AddListPromptsFilter`, `AddGetPromptFilter`, `AddListResourcesFilter`, `AddReadResourceFilter`, `AddListResourceTemplatesFilter`, `AddCompleteFilter`, `AddSubscribeToResourcesFilter`, `AddUnsubscribeFromResourcesFilter`, `AddSetLoggingLevelFilter`.
|
|
240
|
+
|
|
241
|
+
### Identidade por request
|
|
242
|
+
|
|
243
|
+
- **`context.User`** é o `ClaimsPrincipal` do request, disponível dentro do filtro.
|
|
244
|
+
- Uma tool pode receber por **injeção de parâmetro**: `ClaimsPrincipal`, `RequestContext<T>`, `McpServer` e `IProgress<T>`. O escopo de DI é **por request** — `McpServerOptions.ScopeRequests` tem default **`true`** (medido). `[FromKeyedServices]` funciona.
|
|
245
|
+
- **`HttpServerTransportOptions.ConfigureSessionOptions`** permite montar o `ToolCollection` a partir do `HttpContext.User` — poda no nascimento da sessão, complementar (não substituta) ao filtro de `CallTool`.
|
|
246
|
+
|
|
247
|
+
### Argumento de tool é input NÃO confiável
|
|
248
|
+
|
|
249
|
+
O que chega nos argumentos foi escrito por um modelo, a partir de texto que um humano digitou. Trate como entrada hostil:
|
|
250
|
+
|
|
251
|
+
- **Allow-list** de valores onde houver conjunto finito; nunca `switch` com `default:` permissivo.
|
|
252
|
+
- **Limite de tamanho** em toda string antes de tocar I/O.
|
|
253
|
+
- **Query parametrizada**, sempre — nunca concatenação com o argumento.
|
|
254
|
+
- **Id de tenant vem da closure ou da credencial, NUNCA do modelo.** Uma tool que aceita `tenantId` como parâmetro é uma tool que qualquer prompt injection reaponta para outro cliente.
|
|
255
|
+
|
|
256
|
+
**Registrar no Claude Code (`settings.json` do projeto consumidor):**
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"mcpServers": {
|
|
261
|
+
"my-project-tools": {
|
|
262
|
+
"command": "dotnet",
|
|
263
|
+
"args": ["run", "--project", "src/MyProject.McpServer"]
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Tool nativa vs MCP server exposto
|
|
272
|
+
|
|
273
|
+
| Dimensão | Tool nativa (`[Description]`) | MCP server exposto |
|
|
274
|
+
|----------|------------------------------|--------------------|
|
|
275
|
+
| **Consumidor** | Agentes do próprio projeto | Agentes externos (Claude Code, outros projetos) |
|
|
276
|
+
| **Protocolo** | Chamada direta em processo | Protocolo MCP (stdio ou HTTP) |
|
|
277
|
+
| **Descoberta** | Registro manual no agente | `ListTools` — autodescoberta |
|
|
278
|
+
| **Quando usar** | Lógica interna do projeto | Capacidades que cruzam fronteiras de projeto/processo |
|
|
279
|
+
| **Overhead** | Zero | Processo separado, IPC via stdio/HTTP |
|
|
280
|
+
| **Testabilidade** | Unitária com xUnit/nSubstitute | Requer host em execução ou mock do transport |
|
|
281
|
+
|
|
282
|
+
**Regra**: se o único consumidor é um agente do próprio projeto → tool nativa. Se o consumidor é externo → MCP server.
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Segurança
|
|
287
|
+
|
|
288
|
+
Um MCP server exposto é uma **superfície de ataque real** — qualquer agente com acesso ao transporte pode invocar suas tools.
|
|
289
|
+
|
|
290
|
+
**Obrigatório antes de expor:**
|
|
291
|
+
|
|
292
|
+
- **Validação de input:** valide todos os parâmetros recebidos (IDs, datas, strings livres) antes de executar lógica de negócio. MCP não valida tipos por você.
|
|
293
|
+
- **Escopo mínimo:** exponha apenas as tools necessárias. Não exponha operações de escrita se o consumidor só lê.
|
|
294
|
+
- **Autenticação (HTTP transport):** se usar HTTP, exija bearer token ou API key via header. stdio é implicitamente restrito ao processo pai.
|
|
295
|
+
- **Nunca expor secrets via tools:** tools não devem retornar API keys, tokens, ou dados de configuração interna.
|
|
296
|
+
- **Rate limiting:** se o MCP server for exposto via HTTP em produção, adicione rate limiting na camada de transporte (reverse proxy / middleware ASP.NET).
|
|
297
|
+
|
|
298
|
+
A validação de input é mostrada inline no exemplo `GetOrderStatus` acima — valide IDs/datas/strings
|
|
299
|
+
**antes de qualquer I/O** e devolva uma mensagem de erro descritiva (o consumidor é um LLM, que
|
|
300
|
+
corrige o argumento na próxima iteração). Para tools por atributo que precisam de repositories,
|
|
301
|
+
prefira o tipo de instância resolvido por DI a métodos estáticos com estado global.
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Anti-patterns
|
|
306
|
+
|
|
307
|
+
| Anti-pattern | Problema | Solução |
|
|
308
|
+
|-------------|---------|---------|
|
|
309
|
+
| Criar MCP server para tools que só os agentes do próprio projeto usam | Overhead de processo + IPC sem benefício; mais difícil de testar | Tool nativa `[Description]` + `AIFunctionFactory.Create()` |
|
|
310
|
+
| Expor tools sem validação de input | Agentes externos (ou alucinações de LLM) podem enviar dados malformados | Validar todos os parâmetros antes de qualquer I/O |
|
|
311
|
+
| Tools sem escopo definido — expor tudo "por conveniência" | Superfície de ataque ampla; dificulta manutenção | Expor apenas o necessário; revisar a lista a cada release |
|
|
312
|
+
| HTTP transport sem autenticação | Qualquer processo na rede pode invocar as tools | Bearer token / API key obrigatório em HTTP; stdio é suficiente para uso local |
|
|
313
|
+
| **Podar só a listagem e chamar isso de autorização** | `ListTools` filtrado esconde a tool; quem sabe o nome chama assim mesmo, e cliente conectado não relê a lista | `AddListToolsFilter` **e** `AddCallToolFilter` |
|
|
314
|
+
| **`tenantId` como parâmetro de tool** | O argumento é escrito pelo modelo: prompt injection reaponta para outro cliente | Tenant vem da closure ou de `context.User` |
|
|
315
|
+
| Escrever `options.Stateless = true` "para escalar" | Redundante desde a revisão `2026-07-28`; sugere que há uma decisão a tomar onde não há | `WithHttpTransport()` sem argumento |
|
|
316
|
+
| Contar com `initialize`, `Mcp-Session-Id`, `ping` ou `logging/setLevel` | Removidos na revisão `2026-07-28` | Versão/capacidades em `_meta` por request; `server/discover` |
|
|
317
|
+
| Subir o MCP server no mesmo processo da aplicação principal | Acoplamento; falha no servidor MCP afeta a app | Projeto separado (`MyProject.McpServer`) com entrypoint próprio |
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Checklist (verifiable by morph-eval)
|
|
322
|
+
|
|
323
|
+
- [ ] `ModelContextProtocol` e `Microsoft.Agents.AI` no `.csproj`; `ModelContextProtocol.AspNetCore` apenas se HTTP
|
|
324
|
+
- [ ] Tools declaradas via `[McpServerToolType]` + `[McpServerTool]` (estáticas) ou `McpServerTool.Create(...)` (agente MAF / runtime)
|
|
325
|
+
- [ ] `AddMcpServer()` com `WithStdioServerTransport()` (stdio) ou `WithHttpTransport()` (HTTP) — sem reafirmar o default `Stateless`
|
|
326
|
+
- [ ] `WithToolsFromAssembly()` para tools por atributo, ou `WithTools([...])` para tools de runtime
|
|
327
|
+
- [ ] Entrypoint: `await builder.Build().RunAsync()` (stdio) ou `app.MapMcp(); app.Run()` (HTTP)
|
|
328
|
+
- [ ] Agente criado via `_modelRegistry.GetChatClient("alias").AsAIAgent(...)` — provider-agnostic
|
|
329
|
+
- [ ] Validação de input em todas as tools antes de executar lógica de negócio
|
|
330
|
+
- [ ] Escopo mínimo: apenas tools necessárias para o consumidor externo
|
|
331
|
+
- [ ] HTTP transport (se usado) protegido por autenticação
|
|
332
|
+
- [ ] Multi-tenant: existe `AddCallToolFilter`, e não apenas `AddListToolsFilter`
|
|
333
|
+
- [ ] Nenhuma tool recebe id de tenant como parâmetro
|
|
334
|
+
- [ ] Nenhum `PackageReference` com faixa flutuante; pacote fora do pin com data de apuração
|
|
335
|
+
- [ ] Nenhum `Guid.NewGuid()` — usar `Guid.CreateVersion7()` se IDs são necessários
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## References
|
|
340
|
+
|
|
341
|
+
- `ai-agents-setup` — pacotes base MAF, DI, quick start
|
|
342
|
+
- `ai-agents-mcp-tools` — consumir MCP servers externos em um agente MAF
|
|
343
|
+
- `ai-agents-production` — middleware pipeline, `ResilientToolMiddleware`, segurança
|
|
344
|
+
- [ModelContextProtocol C# SDK](https://github.com/modelcontextprotocol/csharp-sdk) — `docs/concepts/filters.md`, `docs/concepts/identity/identity.md` (lidos 2026-09-08)
|
|
345
|
+
- [MCP — versionamento da especificação](https://modelcontextprotocol.io/specification/versioning) e o changelog da revisão `2026-07-28` (lidos 2026-09-08)
|
|
346
|
+
- [NuGet — ModelContextProtocol 2.2.0](https://www.nuget.org/packages/ModelContextProtocol/2.2.0) (publicado 2026-08-13)
|
|
347
|
+
- [Expose Agent as MCP Server — MAF docs](https://learn.microsoft.com/en-us/agent-framework/agents/tools/local-mcp-tools)
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/mcp-server.md v2.0 (2026-09-08)*
|