Power Mission Control: a progressive discovery template for MCP connectors
March 23, 2026
Every MCP connector you’ve built with my Power MCP v2 template follows the same pattern: one AddTool() call per API operation, each with a full JSON Schema. For a five-tool connector, this works great. For an API with 30 operations, the tools/list response alone can consume 15,000 tokens of the planner’s context window—before the agent even does anything.
Power Mission Control changes this. Instead of registering dozens of typed tools, the template exposes three meta-tools that cover any API surface. The planner discovers operations on demand, so full schemas are never injected upfront.
The problem with typed tools at scale
When Copilot Studio’s planner calls tools/list, every registered tool dumps its name, description, and full input schema into the response. A 30-tool connector sends roughly 500 tokens per tool—15,000 tokens total. That’s context window budget spent on tool definitions the planner may never use.
Worse, each new API operation you want to cover requires writing another AddTool() block with custom schema configuration, error handling, and response processing. The developer cost scales linearly with the API surface.
Three tools instead of thirty
Power Mission Control replaces the per-operation pattern with three tools:
| Tool | Purpose |
|---|---|
scan_{service} |
Search for available operations by intent |
launch_{service} |
Execute any API endpoint with auth forwarding |
sequence_{service} |
Execute a sequence of multiple operations in one call |
The {service} suffix comes from your ServiceName configuration. Set it to apiservice, and you get scan_apiservice, launch_apiservice, and sequence_apiservice.
The tools/list payload drops from ~15,000 tokens to ~1,500—a 90% reduction on initial load.
How discovery works
Instead of pre-loading every schema, the planner asks scan_{service} what’s available:
User: "Create a new customer"
Planner → scan_apiservice({query: "create customer"})
← Returns: endpoint /customers, method POST, required params [name, email]
Planner → launch_apiservice({endpoint: "/customers", method: "POST", body: {...}})
← Returns: created customer record
The scan tool searches your capability index—a JSON array of operation descriptions embedded in the connector. Each entry includes an endpoint, HTTP method, outcome description, domain tag, and parameter lists. The planner gets just enough context to select the right operation and request schemas only when needed.
Three discovery modes
The template supports three ways to resolve scan queries:
Static (default)
The capability index lives directly in script.csx. You curate the JSON array at build time. No external calls needed. This works with any API.
Hybrid
Combines the embedded index for operation discovery with live API describe or metadata calls for field schemas. Describe results are cached (default 30 minutes). Best for APIs with runtime metadata endpoints like /describe or introspection queries.
McpChain
Routes discovery queries to an external MCP server—for example, the MS Learn MCP for Microsoft Graph documentation. Results are cached (default 10 minutes). Best for APIs backed by searchable documentation services.
Quick start
1. Configure your service
In Section 1 of script.csx, set your service name and base URL:
private static readonly MissionControlOptions McOptions = new MissionControlOptions
{
ServiceName = "apiservice",
BaseApiUrl = "https://api.example.com/v1",
DiscoveryMode = DiscoveryMode.Static,
MaxDiscoverResults = 3,
};
2. Build the capability index
Use the companion generate-capability-index.prompt.md to create the index from your API docs:
- Open
generate-capability-index.prompt.mdin VS Code - Paste your API documentation (Swagger, Postman collection, or text)
- Copilot generates the JSON array
- Review and paste into the
CAPABILITY_INDEXconstant inscript.csx
Each entry looks like this:
{
"cid": "create_customer",
"endpoint": "/customers",
"method": "POST",
"outcome": "Create a new customer record",
"domain": "crm",
"requiredParams": ["name", "email"],
"optionalParams": ["phone", "company"],
"schemaJson": "{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"email\":{\"type\":\"string\",\"format\":\"email\"}},\"required\":[\"name\",\"email\"]}"
}
3. Configure auth
Update apiDefinition.swagger.json with your API host and auth scheme:
{
"host": "your-api-host.com",
"basePath": "/mcp",
"securityDefinitions": {
"oauth2_auth": { }
}
}
Update apiProperties.json with connection parameters matching your auth.
4. Deploy
Import as a custom connector in Power Platform and add to your Copilot Studio agent.
Built-in capabilities
The template handles common API patterns so you don’t have to code them per-tool:
- Auth forwarding - The connector’s Authorization header passes through to every API call automatically
- 429 retry - Up to three retries with
Retry-Afterheader support - Error translation - 401, 403, and 404 responses become friendly messages with fix suggestions
- Response summarization - HTML stripping, whitespace collapsing, and field truncation to keep responses token-efficient
- Pagination detection - Identifies
@odata.nextLink,nextLink, andnext_page_urlpatterns and tells the planner how to get more results - Smart defaults - Auto-injects
$topfor GET collection endpoints and supports author-defined parameter injection per endpoint pattern - Sequence operations - Sequential execution or native
$batchendpoint support with configurable size
Add custom tools alongside mission control
You don’t have to go all-in on meta-tools. Register typed tools for high-value operations that need custom logic, and let mission control handle the rest:
private void RegisterCustomTools(McpRequestHandler handler)
{
handler.AddTool("get_limits", "Get current API usage limits.",
schema: s => { },
handler: async (args, ct) =>
{
return await SendExternalRequestAsync(
HttpMethod.Get, $"{McOptions.BaseApiUrl}/limits");
});
}
These appear in tools/list alongside the three mission control tools.
Smart defaults
Inject domain-specific parameter defaults that run before every launch call:
McOptions.SmartDefaults = new Dictionary<string, Action<string, JObject>>
{
["/calendar"] = (endpoint, queryParams) =>
{
if (queryParams["startDate"] == null)
queryParams["startDate"] = DateTime.UtcNow.Date.ToString("yyyy-MM-dd");
},
["/events"] = (endpoint, queryParams) =>
{
if (queryParams["$orderby"] == null)
queryParams["$orderby"] = "start/dateTime";
}
};
When to use mission control vs. typed tools
Use mission control (v3) when:
- The API has 10+ operations and token savings matter
- Operations follow standard REST patterns
- You want to cover the entire API surface without registering every endpoint
- The API may evolve—adding operations means updating the index, not writing code
Use typed tools (v2) when:
- You have a small, fixed set of operations (five or fewer)
- Each tool has complex, unique logic that doesn’t fit a generic proxy pattern
- The API requires different auth or processing per operation
Mix both when:
- Most operations are standard REST but a few need custom logic
- You want mission control for discovery and launch but also need specific high-value tools exposed directly
Template files
| File | Purpose |
|---|---|
script.csx |
Connector logic—Section 1 (your config) + Section 2 (framework) |
apiDefinition.swagger.json |
OpenAPI definition with single POST at /mcp/ |
apiProperties.json |
Connector metadata and auth config |
generate-capability-index.prompt.md |
Copilot prompt for generating capability indexes |
Backward compatibility
All v2 constructs work unchanged. Use handler.AddTool(), handler.AddResource(), and handler.AddPrompt() directly—either instead of or alongside mission control mode.