How to Install an MCP Server from the Official Registry
DEV Community

How to Install an MCP Server from the Official Registry

SAFi comes already packaged to handle MCP tool installation, including its own registry search, which looks for MCP servers published at the official MCP registry, https://registry.modelcontextprotocol.io To search for an MCP server is easy. For example, if you want to see whether Smartsheet has published an MCP server in the registry, you search for it with this command. On Docker: docker compose exec app python scripts/safi_mcp.py search smartsheet On bare metal, first move into your SAFi directory and activate the virtual environment, then run the same script: cd /var/www/safi source venv/bin/activate python3 scripts/safi_mcp.py search smartsheet Your prompt changes to show (venv) once the environment is active. That is how you know it worked. If you skip this step, Python will not find SAFi’s dependencies and the script will fail before it does anything. Every bare-metal command in this post assumes you have done those two lines first. When you are finished, deactivate puts your shell back. Reading the result Here is what came back: io.github.christianclaudio/smartsheet-rm (package, v1.0.2) [pypi:mcp-server-smartsheet-rm@1.0.2] MCP server for Smartsheet Resource Management (10,000ft API) time tracking and scheduling. Add one with: scripts/safi_mcp.py add You may also see a few faiss lines above that about AVX2 support. Ignore them. That is the search index loading and it has nothing to do with MCP. Four things in that one line tell you what you are dealing with. io.github.christianclaudio/smartsheet-rm is the name you install by. Note the io.github prefix: this is a server published by an individual developer, not by Smartsheet. It is a community package that talks to Smartsheet’s API, not an official product. That is not a reason to avoid it, but it is a reason to read what it does before you grant anything. (package, ...) means it runs as a process on your own machine. The other kind you will see is a remote server, which is just a URL that the publisher runs and which needs nothing installed locally. v1.0.2 is the version, and it is pinned. Good. A server that updates can change what a tool does behind a name that never changed. [pypi:...] is the ecosystem. pypi means Python and SAFi will launch it with uvx . If it said npm , SAFi would launch it with npx . This detail decides whether you need to install anything first, which is the next section. Installing it Because the registry knows the details, you install by name and SAFi works out the command: # Docker docker compose exec app python scripts/safi_mcp.py add io.github.christianclaudio/smartsheet-rm # Bare metal python3 scripts/safi_mcp.py add io.github.christianclaudio/smartsheet-rm On a fresh install this will refuse, and that is the system working. SAFi checks that the launcher exists before it writes anything, so you get a message naming the missing binary rather than a server that silently never starts: 'uvx' is not on PATH here, so this server could never start. install uv (pip install uv), which provides uvx. SAFi ships with Node and npx , so npm servers work out of the box. It does not ship uv , so a Python server needs it installed once: # Bare metal, with the venv active pip install uv # Docker, add it to your Dockerfile and rebuild, otherwise it disappears # on the next docker compose up --build RUN pip install uv That last point matters on Docker. Installing uv inside a running container works until the next rebuild, and then the server stops connecting for a reason that looks like nothing to do with you. Put it in the image. Then run the add command again and it will save. Installing a remote server instead If your search returns a remote server rather than a package, there is nothing to install locally. You point SAFi at the URL: # Docker docker compose exec app python scripts/safi_mcp.py add --url https://mcp.example.com/mcp \ --key example --label "Example" # Bare metal python3 scripts/safi_mcp.py add --url https://mcp.example.com/mcp \ --key example --label "Example" Some remote servers support per-user sign-in, so each member connects their own account and every call runs as them. Add --auth oauth for those. To find out whether a server offers it, ask the server: curl -s https://mcp.example.com/.well-known/oauth-authorization-server If that returns a document, use --auth oauth . If it returns nothing, the server takes one static credential shared by everybody. Prefer per-user sign-in whenever the data belongs to a person, which is exactly the case with project tools. Each member’s calls then inherit their own permissions in the source system, appear under their own name in that system’s audit log, and stop working when they are offboarded. One shared credential is the right model for a shared resource, such as an internal pricing service, and the wrong one for somebody’s projects. Passing a credential Most servers need an API token. The server’s own documentation tells you which environment variable it reads. This one wants SMARTSHEET_RM_API_TOKEN . Pass it as a reference, never as the value: # Bare metal python3 scripts/safi_mcp.py add io.github.christianclaudio/smartsheet-rm \ --env SMARTSHEET_RM_API_TOKEN='${SMARTSHEET_RM_API_TOKEN}' \ --env SMARTSHEET_RM_READONLY=true Write ${SMARTSHEET_RM_API_TOKEN} literally, exactly as shown, braces and quotes included. SAFi resolves it from the environment when it connects. The real token goes in your .env file, so the server list stays safe to copy, back up and share with a colleague. If the server offers a read-only switch, as this one does, turn it on for the first install. You can relax it later once you know what the tools return. A local server is always one shared identity This is the thing to understand before you give a tool to anybody. A package server is a process on your machine holding one API token. Every member’s agents act as whoever owns that token. Everyone sees whatever that account can see, the source system’s audit log records that account rather than the person who asked, and access does not end when someone leaves the company. That is the correct model for a shared resource, such as an internal pricing service or a company API. It is the wrong model for “show me my projects”, because there is no “my” in it. It does not matter that the service has user logins of its own. Smartsheet has accounts and permissions, but a local server reaches it with one token, so all of that collapses into a single identity on the way through. Per-user sign-in exists in SAFi, and it is the answer to this, but it needs a remote server that implements the MCP authorization specification. A local process cannot take part. That is why some cards in the Tools Catalog have a Sign in button and others do not. So choose deliberately. Use a service account with the narrowest permissions that still make the tools useful, and enable only read tools to begin with. If members genuinely need their own view of their own data, a shared token is not the way to get there. Check your work # Docker docker compose exec app python scripts/safi_mcp.py check docker compose exec app python scripts/safi_mcp.py list # Bare metal python3 scripts/safi_mcp.py check python3 scripts/safi_mcp.py list check connects to every configured server and reports what it found. list shows what is configured and where it came from. You do not need to restart anything. Every write bumps a counter that the running workers watch, so they pick up the new server on their next request. “Connected” does not mean authenticated. When the Tools Catalog shows a server as connected, it means the process started and answered SAFi’s question about what tools it has. That is a local conversation between SAFi and that process. Nothing has contacted the vendor yet. So a server with a missing or wrong API token still shows as connected, with its full tool list. You find out on the first real tool call, which comes back as an authentication error from the vendor rather than as a connection problem in the catalog. The green state is real, it just certifies less than it looks like: the server is installed and running, not that it can reach anything. Nothing is usable until you grant it This is the step people skip. Installing a server puts it in Settings, Tools Catalog, where the server and its tools are visible and completely inactive. Nothing can call them yet. Discovery never grants anything. Three steps make a tool usable: - Policy. In a policy’s Tools and Guardrails step, enable the specifictools that agents under that policy may use. Tool by tool, so you can enablethe one that lists projects and leave the one that deletes them switched off. - Agent. Assign the tools the policy allows. That is what gets advertisedto the model. - The Will. Every single call is checked against that list by exact namebefore it runs. Start with the read-only tools. Get those working, then decide about anything that creates, updates, moves or deletes, and give that one a reviewer. Two things to know before you enable a server you did not write. Its tool descriptions are written by the publisher and go into the model’s context. And a tool result becomes part of the governance record, so whatever it returns inherits that record’s retention. Who is allowed to install what Installing an MCP server is done from the shell, by whoever controls the deployment. That is the only way, for remote servers as much as for packages. There is no admin screen for it and no API route, on purpose. The browser installs nothing. Settings, Tools Catalog is where you see what is installed, where members sign in to servers that support it, and where you confirm what a server offers. It is not a place to add one. This is deliberate rather than unfinished. Installing a server is a decision about what code runs next to your data and what leaves your network, and whoever makes it should already hold the rights that implies. On a deployment serving several organizations, an admin who could instal

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.