MCP servers, over streamable HTTP
A server is a row with a URL; its tools are discovered by a button and cached, then offered beside the built-in ones. Written by hand rather than taken from the reference SDK, because that SDK's transport does its own connecting -- and the one thing that must not be bypassed is check_url on every hop. Owning the transport is the point; the framing beside it is the small part. Sessions are per call: initialize, initialized, the call, a best-effort DELETE. Caching one wants an owner, a TTL, eviction, a lock and a shutdown hook, and the server may expire it under all of that anyway -- ToolContext is a session-free snapshot precisely so nothing in a tool holds live state. A server's names and descriptions reach the model as instructions and are bounded before they do; what it returns is escaped preformatted text, never markdown. Tools are namespaced per server, so two servers exposing "search" do not collide and neither shadows a built-in. Also: a round's calls now run together under a semaphore, results indexed so each tool turn stays paired with its call, and generation.status names what is running -- a remote tool is latency-bound, and a silent pause is what a hang looks like. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
{% from "_macros.html" import icon %}
|
||||
{#
|
||||
One MCP server in the list.
|
||||
|
||||
Swapped in place by the “Test & refresh” button, so this fragment has to be
|
||||
able to render on its own as well as inside the list.
|
||||
#}
|
||||
<div class="model-row {{ 'is-off' if not server.enabled }}" id="mcp-{{ server.id }}">
|
||||
<div class="model-row__main">
|
||||
<div class="model-row__title">
|
||||
<a class="model-row__name" href="/admin/mcp/{{ server.id }}/edit">{{ server.name }}</a>
|
||||
<span class="badge">{{ tool_count }} tool{{ '' if tool_count == 1 else 's' }}</span>
|
||||
{% if not server.enabled %}<span class="badge badge--danger">disabled</span>{% endif %}
|
||||
{% if not server.public %}<span class="badge">restricted</span>{% endif %}
|
||||
{% if server.allow_private %}<span class="badge">private network</span>{% endif %}
|
||||
{% if server.protocol_version %}
|
||||
<span class="badge badge--leaf">MCP {{ server.protocol_version }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<code class="model-row__id">{{ server.slug }} · {{ server.url }}</code>
|
||||
{% if message %}
|
||||
<p class="text-xs {{ 'danger' if message_kind == 'error' else 'faint' }}">{{ message }}</p>
|
||||
{% elif server.last_error %}
|
||||
<p class="text-xs danger">{{ server.last_error }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="model-row__actions">
|
||||
<button class="btn btn--sm" type="button"
|
||||
hx-post="/admin/mcp/{{ server.id }}/test"
|
||||
hx-target="#mcp-{{ server.id }}" hx-swap="outerHTML">
|
||||
{{ icon("refresh", "icon--sm") }} Test & refresh
|
||||
</button>
|
||||
<a class="btn btn--sm" href="/admin/mcp/{{ server.id }}/edit">Edit</a>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user