Course Content
Scenario-Based AI Engineering Questions
26 sections · 146 lessons
How would you expose internal Jira, Confluence and Snowflake data to many AI clients without writing a separate integration for each?
What you need to know
Without MCP, three clients and three data sources mean up to nine custom integrations. With MCP, you write three servers and each client speaks the same protocol.
Design decisions to defend
| Decision | Choice | Why |
|---|---|---|
| Server boundaries | One per domain: jira-mcp, docs-mcp, warehouse-mcp | Separate deploys, permissions and blast radius |
| Transport | stdio for a local developer tool; Streamable HTTP for a shared remote server | stdio runs as a local process; HTTP serves many users |
| Identity | OAuth for the end user; downstream calls made with that user's permissions | The agent never sees more than the person using it |
| Tool surface | Few, narrow, typed tools | Models choose well from a small, well-described set |
| Results | Compact, bounded payloads with ids | Raw API JSON wastes context and hurts accuracy |
Identity, stated carefully
The server must know who is asking. The client gets an OAuth token for the MCP server. The server then calls Jira or Snowflake on that user's behalf, using a downstream credential issued for that user, for example through a token exchange or a separate OAuth grant to Jira.
Two things to avoid. First, a shared service account: the agent would inherit the union of everyone's access, so an intern's question could read the board's documents. Second, "token passthrough", where the server forwards the token it received straight to another API. The MCP security guidance forbids it, because it breaks audit trails and lets a token meant for one service be replayed against another.
Narrow tools beat generic ones
1from mcp.server.fastmcp import FastMCP23mcp = FastMCP("jira")45@mcp.tool()6def search_issues(project: str, status: str = "open", updated_after: str | None = None) -> list[dict]:7 """Find Jira issues in one project. Use for questions about bugs, tasks or their status.8 Returns at most 20 issues with key, title, status and assignee."""9 issues = jira_for_current_user().search(project=project, status=status,10 updated_after=updated_after, limit=20)11 return [{"key": i.key, "title": i.title, "status": i.status, "assignee": i.assignee}12 for i in issues]search_issues(project, status, updated_after) is safer and more accurate than a generic run_jql(query). The model fills three clear fields instead of writing a query language, and the result is capped at 20 compact rows.
Rollout plan
- Read-only first — search and fetch tools only.
- Audit everything — caller, tool, arguments, result size, latency.
- Rate-limit per user — an agent in a loop should not hammer Snowflake.
- Writes behind confirmation — creating or editing issues asks the user before running.
A real-life example
Scenario (illustrative numbers). A fintech's platform team gets requests from three groups: developers want Jira in their IDE assistant, analysts want Snowflake in a chat tool, and support wants Confluence answers inside their agent. Building each by hand would be nine integrations.
They build three MCP servers. The warehouse server exposes two tools, list_tables(schema) and run_readonly_query(sql), and every query runs under the analyst's own Snowflake role with a row limit of 500. In the first month, audit logs show 11,000 tool calls. One logged call tried to read a salary table and was denied by the user's own role, which is the permission model working as designed. Adding a fourth client later took an afternoon of configuration and no new code.
Follow-up questions to expect
- "Why not one server for everything?" — One compromise or outage would take out all data access, and every tool would share one permission model and one deploy cycle.
- "How do you stop prompt injection from a Confluence page?" — Treat fetched content as data, keep write tools behind confirmation, and never let a tool result grant new permissions.
- "How many tools per server?" — As few as cover the tasks; if a client loads many servers, the total tool count is what hurts selection accuracy.