Troubleshooting
The errors that the library throws, what causes each one, and how to correct it.
Each message below comes from the library. Find your message, then apply the correction.
Server errors
Cannot register MCP middleware after connect()
Cannot register MCP middleware after connect() / connectStatelessTransport() has been called
The server instruments its handler maps one time, at the first connect. After that point you cannot add middleware.
Move each mcpMiddleware() call into the function that builds the server. Register the middleware
before you return the server. See protocol middleware.
next() called multiple times
next() called multiple times in middleware for "tools/call"
One middleware called next() two times. Each middleware must call next() one time only.
Look for a conditional branch that calls next(), and then calls it again on a later line. To stop
the chain, do not call next(). Return a result instead.
mcpMiddleware requires a handler function
mcpMiddleware requires a handler function when a filter is provided
You gave a filter as the first argument, but you did not give a handler as the second argument. Add the handler, or remove the filter.
Incompatible MCP SDK version
Incompatible MCP SDK version: expected _requestHandlers and _notificationHandlers on Server
The middleware layer reads two internal maps of the MCP SDK. Your installed SDK does not have them.
Install an SDK version that agrees with the peer dependency range of the package. Look at
peerDependencies in package.json.
A view is already used by another tool
ng-mcp-ui: view "poll" is already used by tool "create_poll".
Tool "cast_vote" cannot also reference it — each view backs exactly one tool.
Each view belongs to one tool. This rule keeps the tool result and the rendered view together.
Give the second tool its own view, or let the second tool return a text result. A tool that only changes state does not need a view. The first tool re-renders with the new state.
Could not resolve the widget entry bundle
ng-mcp-ui: could not resolve the widget entry bundle from index.html.
IndexHtmlViewManifest read the index.html file of the widgets build, but it found no entry
script tag.
Run the widgets build first:
npm run build:widgets
Then confirm that dist/widgets/browser/index.html has a <script type="module"> tag.
Failed to read widgets index.html
ng-mcp-ui: failed to read widgets index.html at "…".
The path is wrong, or the build did not run. Run npm run build:widgets. If the path is wrong,
give the correct dist/widgets/browser/index.html path to IndexHtmlViewManifest.
The dev-server proxy accepts http only
ng-mcp-ui: the widgets dev-server proxy only supports http:// upstreams
You gave a devServerUrl value that is not an http:// URL. The proxy connects to your local
ng serve process, thus the upstream is always plain HTTP.
Set devServerUrl to the ng serve origin, for example http://localhost:4200.
View errors
An inject function throws outside an injection context
Angular throws this error when you call an inject* function from the wrong place. Each inject*
function reads the MCP_ADAPTOR token, therefore Angular DI must be active.
Call the function in a field initializer, in a constructor, or in runInInjectionContext. Do not
call it in a lifecycle hook, in an event handler, or in a setTimeout callback.
export class PollWidget {
private readonly state = injectViewState(); // correct
onClick() {
const state = injectViewState(); // wrong
}
}
File upload, download or selection is not supported in MCP App
File upload is not supported in MCP App.
An MCP Apps host has no file functions. Only an Apps SDK host has them.
Put the call in a try/catch block and give a fallback path. See
files and downloads and the
host support matrix.
setOpenInAppUrl is not implemented in MCP App
setOpenInAppUrl is not implemented in MCP App.
Only an Apps SDK host has this function. Call it in a try/catch block.
selectFiles is not supported by the current host version
selectFiles is not supported by the current host version.
The Apps SDK host is too old, and it does not show a file picker. Give the user another way to supply the file, for example a URL field.
The href parameter is required
The href parameter is required.
You called setOpenInAppUrl with an empty string, or with spaces only. Give a real URL, or do not
call the function.
Behavior that is correct but looks wrong
A call does nothing and writes a warning
Two functions do nothing on an Apps SDK host. They write a warning to the console.
injectRequestSize. An Apps SDK host controls the size of the iframe.injectRegisterViewTool. An Apps SDK host does not support view tools. The function returns an empty disposer, thus your cleanup code stays correct.
These are not errors. See the host support matrix.
download resolves with isError: true
injectDownload().download never throws. It resolves to { isError: true } when the host has no
download function. Test the result:
const result = await download({ contents });
if (result.isError) {
// Show a link instead.
}
An image or font does not load in the view
Two different causes give the same symptom.
- The URL points to the wrong origin. In the iframe, a relative path points to the host, not
to your server. Use the
mcpAssetpipe. - The CSP does not permit the origin. Add the origin to
resourceDomainsin thecspobject of the view config.
You often need both corrections. See Content Security Policy.