different-ai/openwork · error · PluginArchRouteFailure
mcp_server_not_remote
mcp_server_not_remote
Error message
Only declared remote MCP servers with a URL can be configured.
What it means
Thrown as PluginArchRouteFailure(400, 'mcp_server_not_remote') after the server declaration was found but its config record has no `url` field. The store only supports configuring declared remote MCP servers (HTTP/SSE URLs), so local/stdio command-based servers or declarations missing `url` are rejected.
Source
Thrown at ee/apps/den-api/src/routes/org/plugin-system/store.ts:4892
})
await deletePluginMcpRequirementBindingsByIds({ bindingIds: staleBindingIds })
}
function mcpRequirementServerFromVersion(input: {
configObject: ConfigObjectRow
serverName: string
version: ConfigObjectVersionRow
}): PluginMcpRequirementServer {
const spec = parseConfigObjectVersionSpec(input.version)
const serverName = input.serverName.trim()
const entry = marketplaceMcpServerEntries(spec, input.configObject.title).find((candidate) => candidate.name === serverName)
if (!entry) {
throw new PluginArchRouteFailure(404, "mcp_server_not_found", "MCP server declaration not found on this config object.")
}
const url = readRecordString(entry.config, "url")
if (!url) {
throw new PluginArchRouteFailure(400, "mcp_server_not_remote", "Only declared remote MCP servers with a URL can be configured.")
}
return { config: entry.config, name: entry.name, url }
}
function configVersionOwnsImportedExternalMcpConnection(version: ConfigObjectVersionRow, connectionId: string) {
const spec = parseConfigObjectVersionSpec(version)
const metadata = isRecord(spec.metadata) ? spec.metadata : null
const recordedConnectionId = readRecordString(spec, "externalMcpConnectionId")
|| (metadata ? readRecordString(metadata, "externalMcpConnectionId") : null)
const owned = spec.externalMcpConnectionOwnedByPlugin === true
|| metadata?.externalMcpConnectionOwnedByPlugin === true
return owned && recordedConnectionId === connectionId
}
async function assertRemotePluginMcpUrl(url: string) {
let parsed: URL
try {View on GitHub (pinned to 2b7df46e8a)
Solutions
- Add a valid `url` field to the MCP server declaration in the config object spec, converting it to a remote server if it was local/stdio.
- Confirm the key is spelled `url` (not uri/endpoint/address) and is a non-empty string.
- If a local server is genuinely needed, host it as a remote HTTP MCP endpoint and declare that URL instead.
- Check the config object version you are using — a newer version may already declare the remote form.
Example fix
// before (mcpServers in config spec)
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] }
// after
"github": { "url": "https://mcp.github.com/sse" } Defensive patterns
Strategy: validation
Validate before calling
const entry = marketplaceMcpServerEntries(spec, title).find((s) => s.name === serverName)
if (entry && typeof readRecordString(entry.config, "url") !== "string") {
throw new Error(`MCP server '${serverName}' is not remote; add a 'url' field.`)
} Type guard
function isRemoteMcpEntry(entry: { config: Record<string, unknown> }): boolean {
const url = entry.config["url"]
return typeof url === "string" && url.length > 0
} Try / catch
try {
await configureMcpServer({ version, configObject, serverName })
} catch (e) {
if (isPluginArchRouteFailure(e) && e.code === "mcp_server_not_remote") {
// convert declaration to remote or host it via HTTP
}
} Prevention
- Declare marketplace MCP servers with an explicit `url` key
- Prefer remote (HTTP/SSE) transports over stdio for hosted setups
- Validate config specs at publish time, not only at configure time
- Watch for typos like uri/endpoint instead of url
When it happens
Trigger: Resolving an MCP requirement server whose config entry declares a local server (command/args based, no url key) or whose url is absent/empty — readRecordString(entry.config, 'url') returns undefined.
Common situations: Marketplace config declares a stdio-based MCP server (e.g. { command: 'npx', args: [...] }) which the hosted pipeline cannot configure; a declaration typo like 'uri' or 'endpoint' instead of 'url'; url defined but empty string.
Related errors
- protocol "${url.protocol}" is not allowed
- OpenWork Connect MCP metadata is invalid.
- OpenWork-managed OAuth requires a remote MCP URL.
- extensions.add_mcp_url_required
- the hostname does not resolve
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/9d02ab54e534c138.
Report an issue: GitHub.