solidcodersolidcoder
Explore Courses
solidcodersolidcoder
CoursesAboutPrivacy PolicyTerms
© 2026 solidcoder · Practical courses for software engineering interviews.
Home/AI Engineering/Connection Layer (MCP)/Tools, Resources, and Prompts in Practice
Chapters — Connection Layer (MCP)▾

Tools, Resources, and Prompts in Practice

MCP·Building With It·8 min read·Sep 5, 2026

Dynamic tool discovery, letting a server ask the model something mid-task, resource URI design, and writing prompts that actually guide a workflow.

Discovery beats hardcoding

The Notebook server from the last chapter advertises its tools at connection time rather than the host having a fixed list baked in. That sounds like a small detail, but it's what makes a few real things possible: an assistant that picks up new capabilities the moment a server adds them, no client update required; tool selection based on what's actually available right now, not what was available when the assistant was built; and graceful degradation when a server goes offline, since the assistant can simply see it's gone rather than crash trying to call a hardcoded function.

Sampling: letting the server ask the model something

Most of what we've covered so far is the model calling the server. Sampling runs it the other way: a tool, mid-execution, can ask the AI model to generate something and use that result before finishing. Extend the Notebook server's cousin, a small pantry tracker, with a tool that asks the model to turn a list of ingredients into a suggestion:

@mcp.tool()
async def suggest_recipe(context: Context, available_items: list[str]) -> str:
    """Suggest a simple recipe using only the given pantry items"""
    suggestion = await context.sample(
        prompt=f"Suggest one simple recipe using only these ingredients: {', '.join(available_items)}. "
               f"Keep it to 5 steps or fewer.",
        max_tokens=300,
    )
    return suggestion

The tool itself doesn't know how to cook; it hands the reasoning back to the model and returns whatever comes back. This is the pattern behind self-improving tools and multi-stage workflows: a server can lean on the model's reasoning for the part that's genuinely a language task, while handling the parts that are genuinely deterministic (looking up what's actually in the pantry) itself.

Designing resource URIs that make sense

Resources are addressed by URI, and a little care here pays off the same way a well-designed REST API does:

pantry://items/{item_id}
pantry://shelf/{shelf_name}/items
inventory://expiring?within_days={n}
Hierarchical paths
Mirror how someone would naturally describe the data: a shelf contains items, not the other way around.
Query parameters for filters
"Items expiring within 3 days" reads as a filter, not a different resource type.
Stable ids
An item's URI shouldn't change just because its name or quantity did.

Prompts that guide a real workflow

A prompt in MCP isn't a single instruction; it's a reusable starting point for a multi-step task the server knows how to support. A weekly meal-planning prompt for the same pantry server might look like this:

@mcp.prompt()
async def weekly_meal_plan(context: Context) -> str:
    """Guided workflow for planning a week of meals from current pantry stock"""
    return """I'll help you plan meals for the week using what's already in your pantry.

To get started, tell me:
1. How many meals you're planning for
2. Any dietary restrictions to work around
3. Whether you're open to a short grocery run for a few extra items

Once I know that, I'll check what's on hand, flag anything expiring soon so it gets used first, and suggest a plan that minimizes waste."""

The value isn't the text itself, it's that the prompt encodes the sequence a good outcome actually requires: gather constraints, check real inventory, prioritize what's expiring, then suggest. A user typing a one-line request would get a much shallower result than one walked through this sequence.

A pattern worth noticing

All three primitives showed up together in that last example: the prompt structures the conversation, a resource (expiring items) supplies real data partway through, and a tool eventually acts on the plan. Well-built MCP servers rarely use just one primitive in isolation.

Up next2/3
Part 3 · Building With It
Next Chapter →
Designing Tools People Actually Use
7 min · continue reading
→
← Prev Section
How It Works
How the Pieces Fit Together
Next Section →
Running It Well
Security and Trust Boundaries
Part of a free guide

Connection Layer (MCP)

A simple guide to MCP, the protocol that lets AI tools talk to the outside world.

Browse All Guides →
On this page
  • Discovery beats hardcoding
  • Sampling: letting the server ask the model something
  • Designing resource URIs that make sense
  • Prompts that guide a real workflow