Skip to main content
Glama
tachyurgy
by tachyurgy

mcp-app-harness

A small, working reference implementation of the pattern behind an RL-training sandbox: take a real application, run it in a container, and expose it to an agent through a FastMCP server — with populate / snapshot / restore hooks so every episode starts from an identical, known state and any trajectory can be checkpointed and rewound.

It's deliberately tiny (a support-desk service + its MCP integration) so the seams are visible. Swap the demo app for any web/desktop app and the harness structure is unchanged.

┌────────────────┐        MCP tools/resources        ┌────────────────────┐
│  Agent / RL    │  ───────────────────────────────▶ │  FastMCP harness   │
│  policy        │  create_ticket, populate,          │  (mcp_harness/)    │
└────────────────┘  snapshot, restore, tickets://all  └─────────┬──────────┘
                                                                 │ HTTP (httpx)
                                                                 ▼
                                                       ┌────────────────────┐
                                                       │  App under test    │
                                                       │  FastAPI + SQLite  │
                                                       │  (app/)            │
                                                       └────────────────────┘

Why this exists

Integrating an app into a sandbox has three hard parts, and this repo shows a clean answer to each:

  1. Expose the app to an agent. Every product operation is a typed MCP tool (mcp_harness/server.py) and live state is an MCP resource. Schemas come free from the type hints.

  2. Make state reproducible. populate() seeds a deterministic baseline; snapshot() captures full state; restore() re-applies it. restore(snapshot(x)) == x is asserted in the tests (tests/test_hooks.py).

  3. Keep it testable locally. The HTTP client is transport-injectable, so the whole stack runs in-process over httpx.ASGITransport in CI — no sockets, no flakiness — while production uses real HTTP unchanged.

Related MCP server: Corebee MCP Server

Layout

Path

Role

app/

The application under test — a FastAPI + SQLite support desk. Stands in for the third-party app you'd integrate. Ships an /admin state surface (dump/load/reset).

mcp_harness/server.py

The FastMCP server — product tools + lifecycle tools + resources.

mcp_harness/client.py

Transport-injectable async HTTP client to the app.

mcp_harness/hooks.py

populate / snapshot / restore — the sandbox lifecycle contract.

mcp_harness/config.py

Env-driven service configuration (12-factor).

fixtures/seed_baseline.json

Deterministic starting state for populate().

tests/

pytest: app, hooks, and the MCP tools driven via FastMCP's in-memory client.

Dockerfile / docker-compose.yml

One image, two services (app + harness), healthcheck-ordered boot.

Run it

Tests (fastest way to see it work):

uv venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest -q

Locally, two processes:

# terminal 1 — the app under test
./scripts/run_app.sh                       # http://localhost:8080/health

# terminal 2 — an episode: populate → act → snapshot → reset → restore
./scripts/demo_episode.sh

The MCP server:

python -m mcp_harness.server               # stdio (embed in an agent runtime)
MCP_TRANSPORT=http python -m mcp_harness.server   # HTTP transport on :9000

In a sandbox (Docker):

docker compose up --build
# app  → :8080   |   MCP harness (HTTP) → :9000

The MCP surface

Tools: create_ticket, list_tickets, get_ticket, assign_ticket, close_ticket, populate, snapshot, restore. Resources: tickets://all (live ticket list), health://app (liveness).

An agent's loop looks like: populate() → read tickets://all → call ticket tools → snapshot() to checkpoint. An RL runner scores the resulting state and restore()s to branch a new rollout.

Configuration (all via env — no code changes between environments)

Var

Default

Meaning

APP_BASE_URL

http://localhost:8080

Where the harness reaches the app

APP_DB_PATH

:memory:

SQLite path for the app (/data/... to persist on a volume)

MCP_TRANSPORT

stdio

stdio (embedded) or http (sandboxed port)

MCP_HOST / MCP_PORT

0.0.0.0 / 9000

HTTP transport bind

HARNESS_FIXTURE

fixtures/seed_baseline.json

Baseline for populate()

APP_HTTP_TIMEOUT

10

Client timeout (short, so a wedged app fails fast)

Adapting to a real app

app/ is the throwaway part. To integrate a real app:

  • Point AppClient (or a subclass) at the app's actual API.

  • Re-implement the three hooks against whatever state seam the app exposes — a DB volume snapshot, a docker commit, an export/import endpoint, or a management command. The tool/resource layer and the tests don't change.

License

MIT.

Available Tools

8 tools
assign_ticketC

Assign a ticket to someone; moves it to in_progress.

ParametersJSON Schema
NameRequiredDescriptionDefault
assigneeYes
ticket_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.7/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description bears full burden. It discloses that the ticket moves to 'in_progress' status, but does not mention permissions, reversibility, or other potential side effects. This is insufficient for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with no waste, making it concise. However, it lacks structure (e.g., breaking down what the tool does vs. what the parameters are). It is front-loaded but could be slightly more informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (2 parameters, no annotations) and the existence of an output schema (not shown), the description covers the primary action. However, it omits details on error cases, required permissions, or return values, leaving gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, and the description adds no semantic information about the parameters 'ticket_id' or 'assignee'. The word 'someone' vaguely hints at assignee, but no format or constraints are explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'assign' and the resource 'ticket', and adds the behavioral effect 'moves it to in_progress'. It distinguishes from sibling tools like close_ticket and create_ticket, though it could be more specific about what 'someone' means.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives such as close_ticket or create_ticket. There is no mention of context prerequisites or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

close_ticketD

Close a ticket.

ParametersJSON Schema
NameRequiredDescriptionDefault
ticket_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

D1.3/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description must disclose behavioral traits. It only says 'Close a ticket.' without stating irreversibility, side effects, or required permissions. Completely inadequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely brief (2 words) but underspecified. Conciseness is not just shortness; this fails to provide necessary detail. Score 2 for under-specification.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having an output schema, the description lacks all context: usage, parameter meaning, behavioral notes. For a simple tool, more is needed to ensure correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description provides no information about the single parameter 'ticket_id'. The schema defines it, but the description adds zero value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose1/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Close a ticket.' is a direct restatement of the tool name 'close_ticket', providing no additional information. It is a tautology, so score 1.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus siblings like assign_ticket or restore. No context on prerequisites or exclusions. Score 2 for no guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_ticketB

Open a new support ticket. priority ∈ low|normal|high|urgent.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYes
priorityNonormal

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description should disclose behavioral traits. It only mentions opening a ticket and priority, lacking details about side effects, permissions, or what happens if required fields are missing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with no wasted words, but it could be slightly more structured (e.g., separating parameter info).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simplicity (2 params, output exists), the description is incomplete: it lacks details on required permissions, the meaning of priority, and constraints like title uniqueness. It is too brief for full contextual understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description adds value by listing priority enum values ('low|normal|high|urgent'), but it does not explain the 'title' parameter's purpose or format, leaving a gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Open a new support ticket' with a specific verb and resource, and it distinguishes from siblings (assign, close, get, list, etc.) by being the only creation tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for creating a new ticket but provides no explicit guidance on when to use this tool versus alternatives or any exclusion criteria. It is the only creation tool among siblings, so context is somewhat clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_ticketB

Fetch a single ticket by id.

ParametersJSON Schema
NameRequiredDescriptionDefault
ticket_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided; the description only states 'fetch', implying a read-only operation. It does not disclose behavior for missing IDs, authentication needs, rate limits, or output format (despite an output schema existing).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, short sentence with clear front-loaded information. Every word is necessary and contributes to the purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 1-parameter tool with an output schema, the description is minimally adequate. However, lacking annotations and with no mention of error handling or output, it leaves gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% – the parameter ticket_id has no description in the schema, and the tool description adds no extra meaning beyond the schema definition. The parameter name is self-explanatory, but no elaboration on allowed values or sources.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Fetch a single ticket by id.' uses a specific verb ('fetch') and resource ('single ticket'), clearly distinguishing it from sibling tools like list_tickets (list multiple) or create_ticket (create new).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like list_tickets or search variants. The description implies use when a specific ticket ID is known, but lacks explicit context or exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_ticketsA

List tickets, optionally filtered by status (open|in_progress|closed).

ParametersJSON Schema
NameRequiredDescriptionDefault
statusNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose all behavioral traits. It only states listing with optional filtering, omitting critical details like pagination, sorting, rate limits, or read-only behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence with no unnecessary words. It is front-loaded and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return value details are covered. However, the description lacks behavioral context such as ordering, pagination, or limitations, which are needed for a complete understanding despite low complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description adds meaning by listing the valid status values (open|in_progress|closed) beyond the schema's anyOf string/null. This compensates for the lack of schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'list', the resource 'tickets', and the optional filtering by status with specific values (open|in_progress|closed). It distinguishes from sibling tools like create_ticket, close_ticket, etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not specify when to use this tool versus alternatives like get_ticket (single ticket retrieval) or other actions. No explicit when-not or alternative guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

populateC

Reset the app and load the deterministic baseline fixture.

ParametersJSON Schema
NameRequiredDescriptionDefault
fixture_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden. It says 'Reset the app', implying destructive behavior, but does not clarify what is destroyed, whether the operation is reversible, or any side effects. The term 'deterministic baseline fixture' is vague without further explanation of data loss.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise—one sentence with no waste. However, it sacrifices important details for brevity. It is front-loaded with the key verb 'Reset' and noun 'fixture', but could include more without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has an output schema (but not shown) and no required parameters, the description covers the basic functionality. However, for a destructive operation, it should warn about data loss or state changes. The description is adequate for a simple tool but lacks completeness for safe usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the parameter 'fixture_path'. However, the description makes no mention of this parameter—what it does, whether it is required, or how to specify a custom fixture. The parameter is completely ignored.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool resets the app and loads a deterministic baseline fixture. This is distinct from sibling tools like 'restore' (which suggests restoring a previous state) and ticket operations. The verb 'reset' and noun 'fixture' specify the action and resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives like 'restore' or 'snapshot'. There is no mention of prerequisites, intended scenarios, or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

restoreC

Overwrite application state with a previously captured snapshot.

ParametersJSON Schema
NameRequiredDescriptionDefault
stateYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must fully disclose behavior. It mentions overwriting state but does not indicate whether the operation is destructive, what permissions are needed, or what the return value (output schema exists) is.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence, making it concise, but it omits important details. It is front-loaded but could be more informative without losing brevity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of annotations, the description is insufficient. It does not explain the tool's output or behavior beyond the basic action, leaving the agent with significant gaps for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must clarify parameter meaning. It only says 'previously captured snapshot' without explaining that the 'state' parameter is the snapshot object or its required structure.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('overwrite application state') and the source ('previously captured snapshot'). It distinguishes from sibling tools like 'snapshot' which captures state, though it could be more specific about what 'application state' encompasses.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives like 'populate' or 'snapshot'. There is no mention of prerequisites or scenarios where restoring is appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

snapshotB

Capture the full application state as a JSON document.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations exist, so the description must fully describe behavior. It only says 'Capture the full application state', which implies reading, but does not disclose if it is destructive, requires permissions, or alters state. For a snapshot tool, it is unclear if it saves persistently or just returns.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that front-loads the key action and result. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the sibling tools 'populate' and 'restore', the description could clarify that this tool is for capturing state (read) vs restoring (write). An output schema exists, so return values are defined, but the description doesn't mention the output format beyond 'JSON'.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the schema already covers everything. The description does not add parameter semantics, but with 0 params, baseline is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool captures the full application state as JSON. It is specific with verb 'capture' and resource 'application state'. However, it does not differentiate from sibling tools like 'populate' and 'restore', which might be related.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives. There is no mention of prerequisites, typical use cases, or when to avoid it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 8 tool updatesv0.1.0
    • First observedassign_ticket
    • First observedclose_ticket
    • First observedcreate_ticket
    • First observedget_ticket
    • First observedlist_tickets
    • First observedpopulate
    • First observedrestore
    • First observedsnapshot

TDQS

C2.8/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: ticket tools (create, read, update status, list) and state management tools (populate, restore, snapshot) operate on different aspects with no overlap.

Naming Consistency4/5

Ticket tools follow consistent verb_noun pattern (e.g., create_ticket), but state management tools use single-word verbs (populate, restore, snapshot), creating a minor inconsistency in naming conventions.

Tool Count5/5

8 tools is well-scoped for a ticket system with testing utilities; each tool earns its place without being excessive or insufficient.

Completeness3/5

Core ticket lifecycle is covered (create, get, list, assign, close), but missing update for other fields (e.g., priority, description) and no reopen functionality, leaving notable gaps.

Maintenance

ActivityStale
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

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/tachyurgy/mcp-app-harness'

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