Skip to main content
Glama

capman-mcp

MCP (Model Context Protocol) adapter for capman — exposes a capman capability manifest as a typed, governed set of MCP tools callable by Claude Desktop, the Claude API, or any MCP-compatible client.

Version: 0.1.0 · Node.js: ≥ 18 · capman peer: ≥ 0.6.3 · License: MIT


Table of Contents

  1. Overview

  2. Architecture

  3. Installation

  4. Quick start — Claude Desktop

  5. Demo mode

  6. Operating modes

  7. Config reference

  8. Capability filtering

  9. Policy gate and risk levels

  10. Registry

  11. Dependency graph

  12. Catalog service

  13. Matching modes

  14. Verdict handling

  15. Audit log

  16. HTTP transport

  17. Troubleshooting


Related MCP server: Composio MCP Server

Overview

capman-mcp sits between your capman manifest and any MCP client. It reads your manifest, applies a governance layer (approval, privacy, risk), and exposes each approved capability as a typed MCP tool. Every tool call is translated into engine.ask(), the result is validated, logged, and returned as a structured MCP response.

MCP client (Claude Desktop / API)
         │  tools/list + tools/call (MCP protocol)
         ▼
    capman-mcp
    ├── Approval gate    (allowlist or registry)
    ├── Privacy filter   (public only)
    ├── Risk gate        (policyGate — blocks high-risk by default)
    ├── Dependency graph (cycle detection + impact analysis)
    └── Catalog service  (read-only HTTP discovery API)
         │  engine.ask()
         ▼
       capman  (BM25 → LLM → resolve → HTTP)
         │
         ▼
    Your app's REST API

Architecture

capman-mcp is composed of six independent layers, each in its own module:

Module

Responsibility

bridge.ts

Converts manifest capabilities to MCP tool definitions; applies all filters

allowlist.ts

Loads config; validates allowed capability IDs

server.ts

MCP server bootstrap; callTool handler; demo mode

logger.ts

Append-only audit log; JSON (production) or human-readable (demo)

registry.ts

Persistent capability registry; publish, deprecate, diff

risk.ts

Pure risk level derivation from HTTP method, privacy, and error codes

graph.ts

Dependency graph; cycle detection; impact analysis

catalog.ts

Read-only HTTP catalog service

resolve.ts

resolveById — registry-mode bypass of the matcher

schema-derive.ts

Input/output schema derivation from capability definitions

output-validate.ts

Runtime validation of engine results against declared output schemas


Installation

npm install capman-mcp capman

capman is a peer dependency. Install it alongside capman-mcp so you control the version.


Quick start — Claude Desktop

1. Generate your manifest

# From an existing OpenAPI spec
npx capman generate --from openapi.json

# Or from a capman.config.js you wrote
npx capman generate

This produces capman.manifest.json in your working directory.

2. Create capman-mcp.config.js

// capman-mcp.config.js
module.exports = {
  manifest: '/absolute/path/to/capman.manifest.json',
  baseUrl:  'https://api.your-app.com',
  mode:     'balanced',
  dryRun:   false,
  transport: 'stdio',

  allowedCapabilities: [
    { id: 'get_order' },
    { id: 'list_products' },
    { id: 'check_availability' },
  ],

  audit: {
    enabled: true,
    logFile: '.capman/mcp-audit.log',
  },
}

Always use absolute paths. Claude Desktop resolves paths from its own working directory, not yours. Relative paths will silently fail to load.

3. Add capman-mcp to Claude Desktop

Open your Claude Desktop config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Add a new entry under mcpServers:

{
  "mcpServers": {
    "my-app": {
      "command": "npx",
      "args": [
        "capman-mcp",
        "start",
        "--config",
        "/absolute/path/to/capman-mcp.config.js"
      ]
    }
  }
}

4. Test before connecting

Run the server manually first to confirm the config loads cleanly:

npx capman-mcp start --config /absolute/path/to/capman-mcp.config.js

Expected output:

[capman-mcp] Loaded manifest: your-app (12 capabilities)
[capman-mcp] 8 tools registered
[capman-mcp] MCP server running on stdio

5. Restart Claude Desktop

Quit Claude Desktop completely and reopen it. Your capabilities are now available as tools.


Demo mode

Try capman-mcp with a bundled sample manifest — no real app, no config, no API keys:

npx capman-mcp demo

This starts a dryRun: true server with 4 sample e-commerce capabilities. To connect Claude Desktop, add this to claude_desktop_config.json:

{
  "mcpServers": {
    "capman-demo": {
      "command": "npx",
      "args": ["capman-mcp", "demo"]
    }
  }
}

Then restart Claude Desktop and ask: "get order ORD-123" or "list products".


Operating modes

capman-mcp supports two approval modes. Choose one per deployment.

Config mode (default)

The allowedCapabilities array in your config file is the source of truth for which capabilities are exposed. Straightforward for single-service or single-team setups.

allowedCapabilities: [
  { id: 'get_order' },
  { id: 'list_products', descriptionOverride: 'Browse the product catalog' },
  { id: 'delete_account', allowHighRisk: true },
]

Registry mode

Set registryPath to enable registry-based approval. Approval state, risk level, dependency declarations, and deprecation are all stored in a versioned JSON registry file. Intended for teams where a CI pipeline publishes capabilities and a separate approval step gates MCP exposure.

module.exports = {
  manifest:      '/path/to/capman.manifest.json',
  registryPath:  '/path/to/.capman-mcp/registry.json',
  transport:     'stdio',
  // allowedCapabilities can still be used for descriptionOverride / dryRunOverride
  allowedCapabilities: [],
}

In registry mode, resolveById is used instead of engine.ask() — the tool name directly identifies the capability, bypassing the matcher entirely for lower latency.


Config reference

CapmanMcpConfig

Field

Type

Required

Default

Description

manifest

string

Absolute path to capman.manifest.json

baseUrl

string

Base URL for API resolvers

mode

'cheap' | 'balanced' | 'accurate'

'balanced'

Matching mode (config mode only)

dryRun

boolean

false

Plan API calls without executing them

transport

'stdio' | 'http'

'stdio'

MCP transport

httpPort

number

3000

Port when transport: 'http'

allowedCapabilities

AllowedCapabilityEntry[]

✅*

*Required in config mode; optional override layer in registry mode

registryPath

string

Enables registry mode when set

policyGate

boolean

true

Block high-risk capabilities unless explicitly opted in

auth

CapmanMcpAuthConfig

Auth context for the server instance. Required to expose user_owned capabilities

audit.enabled

boolean

true

Enable invocation logging

audit.logFile

string

stderr

Append-only audit log path

AllowedCapabilityEntry

Field

Type

Required

Description

id

string

Capability ID from your manifest

descriptionOverride

string

Replaces the capability description shown in the MCP tool listing

dryRunOverride

boolean

Per-capability dry-run — takes precedence over global dryRun

allowHighRisk

boolean

Explicitly expose this capability despite a high risk level

CapmanMcpAuthConfig

Field

Type

Required

Default

Description

isAuthenticated

boolean

Must be true for user_owned capabilities to be exposed and executed

userId

string

Injected by capman into params marked source: 'session'. Never exposed to the agent

role

'user' | 'admin'

'user'

User's role. admin capabilities remain hard-blocked regardless of this value


Capability filtering

buildToolList applies four filters in order before exposing a capability as an MCP tool. A capability must pass all four to appear.

Filter

Condition to pass

Notes

1. Approval

In allowedCapabilities (config mode) or approvedForMcp: true in registry

2. Privacy

privacy.level === 'public'

user_owned and admin require auth context MCP cannot provide

3. Lifecycle

lifecycle.status !== 'deprecated'

Deprecated capabilities are never surfaced

4. Risk gate

riskLevel !== 'high' OR allowHighRisk: true OR riskOverride: 'allow'

Controlled by policyGate — see below


Exposing user_owned capabilities

By default capman-mcp only exposes public capabilities — those that require no authentication. Many real-world agent workflows need to act on behalf of a specific user: retrieving their orders, updating their account settings, or fetching personalised data. These capabilities have privacy.level === 'user_owned' in the capman manifest.

To expose them, add an auth block to your config:

module.exports = {
  manifest: '/path/to/capman.manifest.json',
  baseUrl:  'https://api.your-app.com',
  transport: 'stdio',

  auth: {
    isAuthenticated: true,
    userId: 'usr-alice-123',  // the user this server instance acts as
    role:   'user',
  },

  allowedCapabilities: [
    { id: 'get_my_orders' },       // user_owned — exposed because auth is set
    { id: 'get_product_catalog' }, // public — always exposed
  ],
}

What auth does

  • The privacy filter in buildToolList allows user_owned capabilities through alongside public ones.

  • capman receives the AuthContext on every tool call and enforces privacy.level at execution time — if isAuthenticated is false, capman rejects the call.

  • capman injects auth.userId into params marked source: 'session' before making the API call. For example, a capability defined with a user_id session param and path /users/{user_id}/orders will automatically call /users/usr-alice-123/orders. The agent never sees or supplies the userId — it is excluded from the MCP input schema entirely.

Privacy levels and auth

privacy.level

No auth

auth.isAuthenticated: true

public

✅ Exposed

✅ Exposed

user_owned

❌ Blocked

✅ Exposed

admin

❌ Blocked

❌ Blocked always

Limitations

This is a static, server-level identity. Every tool call on this server instance runs as the same user. This is correct for:

  • Personal Claude Desktop setups (one person, one server)

  • Single-user API automations

It is not suitable for multi-user deployments where different callers need different identities. Per-request identity requires transport-level auth signal support, which will be added in a future release when the MCP protocol standardises per-request auth headers.


Policy gate and risk levels

Every capability is assigned a risk level automatically on registry publish and at tool-list build time. The derivation rules are applied top-down, first match wins.

Rule

Condition

Risk level

1

privacy.level === 'admin'

high

2

Any CapabilityError.code contains a financial keyword

high

3

Resolver uses POST, PUT, PATCH, or DELETE

medium

4

privacy.level === 'user_owned'

medium

5

GET/HEAD/OPTIONS + public privacy

low

Financial keywords (matched case-insensitively as substrings of the error code): payment, charge, billing, financial, refund, invoice, subscription.

policyGate

When policyGate is true (the default), high-risk capabilities are blocked from MCP exposure unless explicitly opted in.

module.exports = {
  policyGate: true,   // default — safe for production
  allowedCapabilities: [
    { id: 'get_order' },                           // low risk — passes automatically
    { id: 'delete_account', allowHighRisk: true }, // high risk — opted in explicitly
  ],
}

Disable the gate only for fully trusted internal deployments:

policyGate: false

Registry mode risk overrides

In registry mode, each RegistryEntry carries a riskOverride field that takes precedence over the computed riskLevel:

riskOverride value

Effect

'allow'

Expose despite high risk (operator has reviewed and approved)

'block'

Never expose, regardless of risk level (hard block)

absent

Default gate behaviour

{
  "fullyQualifiedId": "my-app/create_payment",
  "riskLevel": "high",
  "riskOverride": "allow",
  "approvedForMcp": true
}

Registry

The registry is a persistent JSON file that tracks every published capability with its approval state, risk level, schema hash, and dependency declarations. It is the source of truth in registry mode and the backing store for the catalog service.

CLI commands

# Publish all capabilities from a manifest into the registry
capman-mcp registry publish --manifest capman.manifest.json --owner ci-bot

# Publish without approving for MCP (pending review state)
capman-mcp registry publish --manifest capman.manifest.json --no-approved-for-mcp

# List all registry entries with status, risk, and approval state
capman-mcp registry list

# Show what would change if you published a new manifest version
capman-mcp registry diff --manifest capman.manifest.json

# Deprecate a capability (with optional successor)
capman-mcp registry deprecate my-app/old_endpoint --successor my-app/new_endpoint

# Show all capabilities that depend on a given capability
capman-mcp registry impact my-app/get_order

# All commands accept --registry <path> to target a non-default registry file

registry list output

ID                                    STATUS    RISK     APPROVED  OWNER
my-app/get_order                      stable    low      true      ci-bot
my-app/create_payment                 stable    high     false     ci-bot
my-app/old_search                     deprecated medium  true      ci-bot

registry diff output

  ~ [changed] [low]    my-app/get_order
  + [new]     [medium] my-app/create_refund
  - [removed]          my-app/legacy_checkout
    [unchanged]        my-app/list_products

RegistryEntry fields

Field

Type

Description

fullyQualifiedId

string

"{appSlug}/{capabilityId}"

schemaVersion

string

Manifest schema version at publish time

owner

string

Team or CI identity that last published

status

LifecycleStatus

stable, beta, experimental, deprecated

schemaHash

string

SHA-256 of the capability definition

approvedForMcp

boolean

Whether this capability is exposed via MCP

riskLevel

'low' | 'medium' | 'high'

Auto-derived on publish

riskOverride

'allow' | 'block'

Operator override (optional)

dependsOn

string[]

Explicit dependency declarations (optional)

publishedAt

string

ISO 8601 timestamp of last publish

deprecatedAt

string

ISO 8601 timestamp of deprecation (optional)

successor

string

fullyQualifiedId of the replacement (optional)


Dependency graph

Declaring dependencies

Set dependsOn on a registry entry to declare that one capability relies on another. Values are fullyQualifiedId strings:

{
  "fullyQualifiedId": "my-shop/order_summary",
  "dependsOn": ["my-shop/get_order", "my-shop/get_customer"]
}

Cycle detection

Cycle detection runs automatically on every registry publish. If a publish would introduce a circular dependency chain, it is rejected before the registry file is written — the operation is atomic.

Error: Circular dependency detected: my-shop/a → my-shop/b → my-shop/c → my-shop/a
Fix: remove one of the dependsOn declarations that forms this cycle.

Impact analysis

Find all capabilities that would be affected if a given capability changes:

capman-mcp registry impact my-shop/get_order
Impact analysis for: my-shop/get_order
2 capabilities would be affected if this changes:

  my-shop/order_summary   (stable, medium)
  my-shop/checkout_flow   (stable, low)

This performs a reverse-graph BFS — it finds every capability that directly or transitively depends on the given one, not just its immediate consumers.


Catalog service

The catalog is a read-only HTTP service that makes your capability registry discoverable. Start it alongside your MCP server or as a standalone process:

capman-mcp catalog start --port 4001 --manifest capman.manifest.json
[capman-mcp] Catalog server running at http://localhost:4001
[capman-mcp] Endpoints:
[capman-mcp]   GET /health
[capman-mcp]   GET /capabilities
[capman-mcp]   GET /capabilities/:fqId
[capman-mcp]   GET /capabilities/:fqId/badge
[capman-mcp]   GET /capabilities/:fqId/impact

The catalog reloads the registry on every request — it always reflects the current state without a restart.

Endpoints

Endpoint

Response

GET /health

{ ok: true, count: N }

GET /capabilities

RegistryEntry[] — supports filters

GET /capabilities/:fqId

Single RegistryEntry or 404

GET /capabilities/:fqId/badge

SVG compatibility badge

GET /capabilities/:fqId/impact

{ fullyQualifiedId, impacted: string[] }

Query filters for GET /capabilities

Parameter

Example

Effect

q

?q=order

Case-insensitive substring match on fullyQualifiedId and owner

risk

?risk=high

Filter by low, medium, or high

status

?status=stable

Filter by lifecycle status

approvedForMcp

?approvedForMcp=false

Filter by approval state

Parameters combine: GET /capabilities?risk=high&approvedForMcp=true

Badge colours

Embed a capability's MCP compatibility badge anywhere SVG is supported:

<img src="http://localhost:4001/capabilities/my-app/get_order/badge" />

Colour

Meaning

🟢 Green

approvedForMcp: true, risk level low or medium

🟡 Amber

approvedForMcp: true, risk level high — review recommended

🔴 Red

approvedForMcp: false or riskOverride: 'block'


Matching modes

capman-mcp delegates matching to capman's engine. Three modes trade API cost against matching accuracy. The mode is set per-server in config.

Mode

Behaviour

Best for

cheap

BM25 keyword only — zero LLM calls

Registry mode (tool name is explicit)

balanced

Keyword first; LLM fallback when confidence < 50%

Most production deployments

accurate

LLM over top-3 candidates on every call

High-ambiguity capability sets

In registry mode, resolveById is used instead of engine.ask(), making the matching mode irrelevant — the tool name is an exact capability ID.


Verdict handling

Each engine.ask() call returns a verdict that capman-mcp surfaces in the MCP response:

Verdict

Meaning

MCP response

clear

High-confidence match, large margin over runner-up

Returned as-is

marginal

Top two candidates are close in score

Prefixed with [verdict: marginal]

uncertain

Confidence below threshold

Prefixed with [verdict: uncertain]

The client (Claude) sees the verdict annotation and can ask for user confirmation before acting on a marginal result.


Audit log

When audit.enabled is true, every tool invocation is written as one JSON line:

{
  "ts": "2026-06-13T09:00:00.000Z",
  "capabilityId": "get_order",
  "verdict": "clear",
  "resolvedVia": "keyword",
  "durationMs": 42,
  "dryRun": false,
  "params": ["order_id"],
  "error": null
}

Param values are never logged — only param names. The log is append-only and safe to tail in production. In demo mode, the log is written in human-readable format instead.


HTTP transport

For integrations that cannot use stdio:

module.exports = {
  transport: 'http',
  httpPort:  3000,
}
npx capman-mcp start --config capman-mcp.config.js
# [capman-mcp] MCP server listening on http://localhost:3000

Troubleshooting

Claude Desktop shows no tools after restart

  • Ensure all paths in claude_desktop_config.json are absolute.

  • Run the start command manually in a terminal to see errors directly:

    npx capman-mcp start --config /absolute/path/to/capman-mcp.config.js
  • Verify the manifest is valid: npx capman validate

Error: config.manifest must be a non-empty string path

The manifest field is missing from your config or is not a string.

allowlist entry "X" not found in manifest

The ID in allowedCapabilities does not exist in your manifest. Run npx capman inspect to list all valid capability IDs.

allowlist entry "X" filtered out (non-public or deprecated)

The capability exists but has privacy.level !== 'public' or is deprecated. It cannot be exposed as an MCP tool.

Tool calls return Missing required parameters: <name>

capman could not extract the parameter from the query string. In balanced or accurate mode, capman will attempt LLM extraction automatically. In cheap mode, the parameter value must appear literally in the query. Add more examples to the capability definition to improve extraction.

Circular dependency detected: ...

A registry publish was rejected because dependsOn declarations form a cycle. Remove one of the declarations named in the error path.

enrichWithOutputSchemas does not support YAML specs yet

Convert your OpenAPI spec to JSON before calling enrichWithOutputSchemas:

npx js-yaml your-spec.yaml > your-spec.json

License

MIT

A
license - permissive license
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    Security-enforcing MCP proxy that sits between an AI agent and any number of downstream MCP servers, intercepting every tool call through a capability-token policy gateway that can allow, deny, or escalate to human approval before the call reaches any real tool. It also exposes built-in operator tools for approval workflows, audit trail queries, token management, voice/HUD output, and hierarchical
    21
    12
    Apache 2.0
  • F
    license
    Not graded
    quality
    C
    maintenance
    Turns OpenAPI specs into MCP tools with secure defaults, risk inspection, confirmation gates, response limits, audit logging, and secret redaction.

View all related MCP servers

Related MCP Connectors

  • Runtime permission, approval, and audit layer for AI agent tool execution.

  • Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.

  • AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Hobbydefiningdoctory/capman-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server