-
Notifications
You must be signed in to change notification settings - Fork 2.7k
blog: add 5 tips for building MCP Apps that work #6855
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- New blog post co-authored with Matthew Wang (MCPJam) - Add Matt Wang as new author in authors.yml - Covers: host environment adaptation, data flow control, loading/error states, model sync, and tool visibility
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds a new blog post covering five practical tips for building MCP Apps, including supporting diagrams/screenshots and a new co-author entry.
Changes:
- Add a new blog post: “5 Tips for Building MCP Apps That Work”.
- Add Matthew Wang as a blog author in
authors.yml. - Add new blog images used by the post (banner, flow diagram, loading state screenshot).
Reviewed changes
Copilot reviewed 2 out of 6 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| documentation/blog/authors.yml | Adds new matt author profile for the co-authored post. |
| documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md | New blog content, code examples, and social metadata for the post. |
| documentation/blog/2026-01-30-5-tips-building-mcp-apps/loading-state.png | New image asset referenced by the post. |
documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md
Outdated
Show resolved
Hide resolved
documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md
Outdated
Show resolved
Hide resolved
documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md
Outdated
Show resolved
Hide resolved
documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md
Outdated
Show resolved
Hide resolved
documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <[email protected]>
documentation/blog/2026-01-30-5-tips-building-mcp-apps/index.md
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 6 changed files in this pull request and generated 2 comments.
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 2 out of 6 changed files in this pull request and generated 3 comments.
| import { useApp } from "@modelcontextprotocol/ext-apps/react"; | ||
|
|
||
| function CocktailApp() { | ||
| const [cocktail, setCocktail] = useState<CocktailData | null>(null); | ||
|
|
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The loading-state React example uses useState but doesn't import it, so the snippet as written won't run; add useState to the React import (or qualify it) to keep the example self-contained.
| ui: { resourceUri: "ui://cocktail/cocktail-recipe-widget.html" }, | ||
| visibility: ["model", "app"], |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this tool definition, visibility is placed at _meta.visibility, but elsewhere in the post it is nested under _meta.ui.visibility; hosts in this repo read UI metadata from _meta.ui.*, so move visibility under the ui object for consistency and to match how the host discovers UI metadata.
| ui: { resourceUri: "ui://cocktail/cocktail-recipe-widget.html" }, | |
| visibility: ["model", "app"], | |
| ui: { resourceUri: "ui://cocktail/cocktail-recipe-widget.html", visibility: ["model", "app"] }, |
| return { | ||
| content: [ | ||
| { type: "text", text: `Could not load cocktail` }, | ||
| ], | ||
| error |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The catch block returns the raw error object from the backend to both the model and the MCP App view, which can expose internal details such as stack traces, database errors, or configuration information to end users. An attacker can trigger failing requests (e.g., invalid IDs or crafted payloads) to harvest these internal error messages and use them to map the backend or discover weaknesses. Instead, return a generic, user-safe error message and log the detailed error server-side, ensuring the tool result only contains sanitized error information.
| return { | |
| content: [ | |
| { type: "text", text: `Could not load cocktail` }, | |
| ], | |
| error | |
| // Log the detailed error server-side instead of returning it to the client. | |
| console.error("Failed to load cocktail", error); | |
| return { | |
| content: [ | |
| { type: "text", text: `Could not load cocktail` }, | |
| ], | |
| error: { | |
| message: "Failed to load cocktail.", | |
| }, |
* main: fix: fixed the broken release (#6887) feat: Streamable HTTP transport for ACP + goose-acp usage (#6741) Add Laminar for Observability (#6514) Missed a couple of places that hard code J for the newline key (#6853) fix(ui): preserve working directory when creating new chat (#6789) blog: add 5 tips for building MCP Apps that work (#6855) docs: session isolation (#6846) upgrade react and electron to latest (#6845) Fix: Small update UI settings prompt injection (#6830) Remove autogenerated .gooseignore files that don't belong in repo (#6824) Fix case-insensitive matching for builtin extension names (#6825) docs: cli newline keybinding (#6823) Update version to 1.22.0 (#6821) Refactor: move persisting extension to session outside of route (#6685) acp: load configured extensions and refactor tests (#6803)
Type of Change