| 1 | <div align="center"> |
| 2 | |
| 3 | <!-- omit in toc --> |
| 4 | |
| 5 | <picture> |
| 6 | <img width="900" alt="Concierge Banner" src="assets/concierge-banner.png" /> |
| 7 | </picture> |
| 8 | |
| 9 | # Concierge AI 🚀 |
| 10 | |
| 11 | <strong>The fabric for reliable MCP servers and AI applications.</strong> |
| 12 | |
| 13 | [](https://docs.getconcierge.app) |
| 14 | [](https://discord.gg/Y3ayRa33Pg) |
| 15 | [](https://pypi.org/project/concierge-sdk) |
| 16 | [](https://pypi.org/project/concierge-sdk) |
| 17 | |
| 18 | </div> |
| 19 | |
| 20 | The [Model Context Protocol](https://modelcontextprotocol.io) (MCP) is a standardized way to connect AI agents to tools. Instead of exposing a flat list of every tool on every request, Concierge progressively discloses only what's relevant. Concierge guarantees deterministic results and reliable tool invocation. |
| 21 | |
| 22 | ## Getting Started |
| 23 | |
| 24 | > [!NOTE] |
| 25 | > Concierge requires Python 3.9+. We recommend installing with [uv](https://docs.astral.sh/uv/) for faster dependency resolution, but pip works just as well. |
| 26 | |
| 27 | ```bash |
| 28 | pip install concierge-sdk |
| 29 | ``` |
| 30 | |
| 31 | **Scaffold a new project:** |
| 32 | |
| 33 | ```bash |
| 34 | concierge init my-store # Generate a ready to run project |
| 35 | cd my-store # Enter project |
| 36 | python main.py # Start the MCP server |
| 37 | ``` |
| 38 | |
| 39 | **Or wrap an existing MCP server** two lines, nothing else changes: |
| 40 | |
| 41 | ```python |
| 42 | # Before |
| 43 | from mcp.server.fastmcp import FastMCP |
| 44 | app = FastMCP("my-server") |
| 45 | |
| 46 | # After: just wrap it |
| 47 | from concierge import Concierge |
| 48 | app = Concierge(FastMCP("my-server")) |
| 49 | ``` |
| 50 | |
| 51 | > [!TIP] |
| 52 | > Concierge works at the MCP protocol level. It dynamically changes which tools are returned by `tools/list` based on the current workflow step. The agent and client don't need to know Concierge exists, they just see fewer, more relevant tools at each point. |
| 53 | |
| 54 | <br /> |
| 55 | |
| 56 | ```python |
| 57 | from concierge import Concierge |
| 58 | from mcp.server.fastmcp import FastMCP |
| 59 | |
| 60 | app = Concierge(FastMCP("my-server")) |
| 61 | |
| 62 | # Your @app.tool() decorators stay exactly the same. |
| 63 | # You can additionally add app.stages and app.transitions. |
| 64 | ``` |
| 65 | |
| 66 | > [!NOTE] |
| 67 | > The wrap and go gives you progressive tool disclosure immediately. Add `app.stages` and `app.transitions` when you want full workflow control, no code changes required. |
| 68 | |
| 69 | <br /> |
| 70 | |
| 71 | ## Usage |
| 72 | |
| 73 | ### Group tools into steps |
| 74 | |
| 75 | Instead of exposing everything at once, group related tools together. Only the current step's tools are visible to the agent: |
| 76 | |
| 77 | ```python |
| 78 | app.stages = { |
| 79 | "browse": ["search_products", "view_product"], |
| 80 | "cart": ["add_to_cart", "remove_from_cart", "view_cart"], |
| 81 | "checkout": ["apply_coupon", "complete_purchase"], |
| 82 | } |
| 83 | ``` |
| 84 | |
| 85 | ### Define transitions |
| 86 | |
| 87 | Control which steps can follow which. The agent moves forward (or backward) only along paths you allow: |
| 88 | |
| 89 | ```python |
| 90 | app.transitions = { |
| 91 | "browse": ["cart"], # Can only move to cart |
| 92 | "cart": ["browse", "checkout"], # Can go back or proceed |
| 93 | "checkout": [], # Terminal step |
| 94 | } |
| 95 | ``` |
| 96 | |
| 97 | <details> |
| 98 | <summary><b>Share state between steps</b></summary> |
| 99 | <br> |
| 100 | |
| 101 | Pass data between workflow steps without round-tripping through the LLM. State is session-scoped and works across distributed replicas: |
| 102 | |
| 103 | ```python |
| 104 | # In the "browse" step - save a selection |
| 105 | app.set_state("selected_product", {"id": "p1", "name": "Laptop"}) |
| 106 | |
| 107 | # In the "cart" step retrieve it directly |
| 108 | product = app.get_state("selected_product") |
| 109 | ``` |
| 110 | </details> |
| 111 | |
| 112 | <details> |
| 113 | <summary><b>Scale with semantic search</b></summary> |
| 114 | <br> |
| 115 | |
| 116 | When you have hundreds of tools, enable semantic search to collapse your entire API behind two meta-tools: |
| 117 | |
| 118 | ```python |
| 119 | from concierge import Concierge, Config, ProviderType |
| 120 | |
| 121 | app = Concierge("large-api", config=Config( |
| 122 | provider_type=ProviderType.SEARCH, |
| 123 | max_results=5, |
| 124 | )) |
| 125 | ``` |
| 126 | |
| 127 | No matter how many tools you register, the agent only ever sees: |
| 128 | |
| 129 | ``` |
| 130 | search_tools(query: st |