Production-grade platform engineering handbook — Kubernetes, Terraform, Flux CD, GitHub Actions, AWS, and more.
67
84%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
For managing AWS MCP servers across multiple accounts (SSO, Granted, assumed-role chains, credential_process, team sharing):
→ See references/aws-mcp-profiles.md
Commands: /platform-skills:aws-profile · /platform-skills:mcp configure-aws
MCP is a JSON-RPC 2.0 protocol that connects AI hosts (Claude Desktop, Claude Code) with servers exposing tools, resources, and prompts.
Host (client) MCP Server
│ │
│──── initialize ───────────────>│ negotiate capabilities
│<─── initialized ───────────────│
│ │
│──── tools/list ───────────────>│ discover tools
│<─── { tools: [...] } ──────────│
│ │
│──── tools/call ───────────────>│ invoke tool
│<─── { content: [...] } ────────│
│ │
│──── resources/list ───────────>│ discover resources
│<─── { resources: [...] } ──────│
│ │
│──── resources/read ───────────>│ read resource
│<─── { contents: [...] } ───────│| Transport | Use Case | Notes |
|---|---|---|
stdio | Local CLI tools, Claude Desktop | Process-level isolation, simplest |
SSE (HTTP) | Remote servers, web services | Requires auth layer |
HTTP (Streamable) | Production APIs | Preferred for new remote servers |
npx @modelcontextprotocol/create-server my-server
cd my-server && npm installimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "my-server", version: "1.0.0" });
server.tool(
"search_docs",
"Search internal documentation by keyword",
{
query: z.string().min(1).describe("Search query"),
limit: z.number().int().min(1).max(50).default(10),
},
async ({ query, limit }) => {
const results = await searchIndex(query, limit);
return {
content: [{ type: "text", text: JSON.stringify(results) }],
};
}
);server.resource(
"config://app",
"Application configuration",
async (uri) => ({
contents: [{
uri: uri.href,
text: JSON.stringify(getConfig()),
mimeType: "application/json",
}],
})
);
// Parameterised resource template
server.resource(
"user://{userId}/profile",
"User profile by ID",
async (uri, { userId }) => ({
contents: [{
uri: uri.href,
text: JSON.stringify(await getUserProfile(userId)),
mimeType: "application/json",
}],
})
);server.prompt(
"summarise_pr",
"Summarise a pull request for a code review",
{
pr_url: z.string().url(),
style: z.enum(["brief", "detailed"]).default("brief"),
},
async ({ pr_url, style }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `Summarise this PR in ${style} style: ${pr_url}`,
},
}],
})
);const transport = new StdioServerTransport();
await server.connect(transport);import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import express from "express";
const app = express();
const transports = new Map<string, SSEServerTransport>();
app.get("/sse", async (req, res) => {
const transport = new SSEServerTransport("/message", res);
transports.set(transport.sessionId, transport);
await server.connect(transport);
});
app.post("/message", async (req, res) => {
const sessionId = req.query.sessionId as string;
const transport = transports.get(sessionId);
await transport?.handlePostMessage(req, res);
});
app.listen(3000);pip install mcpimport json
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
mcp = FastMCP("my-server")
class SearchInput(BaseModel):
query: str = Field(description="Search query string")
limit: int = Field(default=10, ge=1, le=50, description="Maximum results")
@mcp.tool()
async def search_docs(input: SearchInput) -> str:
"""Search internal documentation by keyword."""
results = await search_index(input.query, input.limit)
return json.dumps(results)@mcp.resource("config://app")
async def app_config() -> str:
"""Expose application configuration."""
return json.dumps(get_config())
@mcp.resource("user://{user_id}/profile")
async def user_profile(user_id: str) -> str:
"""User profile by ID."""
return json.dumps(await get_user_profile(user_id))if __name__ == "__main__":
mcp.run() # stdio (default)
# mcp.run(transport="sse") # SSE// Good — narrow, descriptive schemas
const InputSchema = z.object({
environment: z.enum(["dev", "staging", "prod"]),
timeout_ms: z.number().int().min(100).max(30_000).default(5_000),
tags: z.array(z.string().max(64)).max(20).optional(),
});
// Bad — overly permissive
const BadSchema = z.object({
data: z.any(), // ❌ no validation
config: z.object({}), // ❌ empty object
});from pydantic import BaseModel, Field, validator
class SearchInput(BaseModel):
query: str = Field(..., min_length=1, max_length=500)
limit: int = Field(10, ge=1, le=50)
filters: list[str] = Field(default_factory=list)
@validator("filters")
def no_empty_filters(cls, v):
return [f.strip() for f in v if f.strip()]// TypeScript — return structured errors, never throw to client
server.tool("risky_op", "...", { id: z.string() }, async ({ id }) => {
try {
const result = await performOperation(id);
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (err) {
return {
content: [{ type: "text", text: `Error: ${err.message}` }],
isError: true,
};
}
});# Python — return error content, never let exceptions propagate unhandled
@mcp.tool()
async def risky_op(id: str) -> str:
try:
return json.dumps(await perform_operation(id))
except OperationError as e:
return f"Error: {e}"# Launch interactive protocol debugger
npx @modelcontextprotocol/inspector node dist/index.jsVerify:
content arraysisError: true# List tools via stdio
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
| node dist/index.jsapp.use((req, res, next) => {
const token = req.headers.authorization?.split(" ")[1];
if (!verifyToken(token)) return res.status(401).json({ error: "Unauthorized" });
next();
});import rateLimit from "express-rate-limit";
app.use("/message", rateLimit({
windowMs: 60 * 1000,
max: 100,
message: { error: "Too many requests" },
}));// ❌ Never expose credentials in tool output
return { content: [{ type: "text", text: JSON.stringify({ apiKey: process.env.SECRET }) }] };
// ✅ Return only what the client needs
return { content: [{ type: "text", text: JSON.stringify({ status: "authenticated" }) }] };isError: true, not unhandled exceptionsprocess.env / os.environ).claude-plugin
.github
commands
docs
examples
agent-self-improve
argocd
awesome-docs
aws
cloudfront
functions
lambda-edge
functions
azure
compliance
conventional-commits
datadog
llm-observability
demo
documentation
dora
dynatrace
fluxcd
github-actions
composite-actions
configure-cloud
db-migrate
docker-build-push
k8s-deploy
notify-slack
pr-comment
release-tag
security-scan
setup-env
setup-terraform
terraform-plan
helm
web-service
templates
kubernetes
kyverno
mcp
observability
openshift
pr-review
ownership
runtime-security
supply-chain
terraform
references
scripts
skills
platform-skills
tests