# Lifecycle And Limits

This package is intentionally small for v0. It resolves Agent 365 MCP tools once
per turn and cleans them up when the turn ends.

## Per-Turn Lifecycle

For each user message:

1. agent-core starts a turn.
2. this provider resolves the active M365 `TurnContext`.
3. Microsoft's SDK resolves MCP server configs.
4. this provider optionally filters those server configs.
5. the default connector creates an agent-core MCP manager.
6. the MCP manager connects the servers and lists tools.
7. those tools are exposed to the model for the current turn.
8. cleanup closes the MCP manager after the turn.

## Filtering

Use `filterServers` to gate or subset discovered MCP servers before connection:

```ts
createA365ToolingCapabilityProvider({
  authorization,
  authHandlerName: "agentic",
  filterServers: (servers) =>
    servers.filter((server) => server.mcpServerName.startsWith("soc_")),
});
```

The input array is newly resolved for the active turn. Returning a new array is
recommended when filtering or reordering.

## Connector Replacement

Use `connectMcpServers` to replace the default per-turn MCP connector.

That is the extension point for:

- connection pooling;
- custom token refresh;
- custom logging;
- custom partial-failure policy;
- per-tenant or per-user MCP client reuse.

The default connector does this:

```txt
A365 server configs -> agent-core MCP config -> createMCPManager() -> getTools()
```

and returns cleanup that closes the manager.

## Latency

One turn performs one A365 tooling discovery round and one MCP connect round.
Expect overhead from:

- gateway token exchange;
- tooling gateway discovery;
- per-audience token exchange;
- MCP initialize/list handshakes.

For several MCP servers this can be noticeable. v0 does not pool clients.

## Token TTL

Microsoft's SDK attaches bearer tokens to returned MCP server headers. The
default connector snapshots those headers into MCP clients at connect time.

Long-running turns may outlive bearer token TTL. v0 does not refresh MCP
Authorization headers mid-turn.

Future token refresh should live behind `connectMcpServers`, not in agent-core.

## Cleanup

The default cleanup calls `manager.close()`.

There is no package-level close timeout in v0. If production deployments show
tail-latency spikes during turn cleanup, add a future `closeTimeoutMs` option to
the connector path.

## Chat History Submission

`createA365ChatHistoryMiddleware()` is opt-in and runs after a completed
agent-core turn. It reads recent messages through the lazy lifecycle history
accessor, converts them to Microsoft's chat-history shape, and calls
`sendChatHistory`.

The middleware submits transport registration only. It does not turn the RTP
call into a synchronous blocking verdict, and failures are non-blocking by
default.

## Abort

`AgentCapabilityContext.abort` is passed to providers, but agent-core's MCP
manager does not currently accept an abort signal for connection setup.

If a user aborts while MCP servers are connecting, v0 waits for the active MCP
connect/list operation to finish or hit `serverTimeoutMs`.

## Partial Failures

agent-core's MCP manager tolerates partial server failures. If one server fails
to connect, healthy servers can still provide tools.

The default per-server timeout is 5000 ms so one flaky server does not add the
default 30 second MCP timeout to every turn.

## Not In V0

v0 does not include:

- cross-turn MCP client pooling;
- mid-turn token refresh;
- inline real-time threat protection blocking;
- generic platform-neutral MCP discovery abstraction;
- dedicated cleanup timeout;
- custom telemetry events for per-server partial failure.

Those can be added later without changing agent-core's capability-provider contract.
