url MCP tool: encode, decode and parse URLs from an AI agent
· 6 min read
Get the devtoolbox.cc MCP serverOpen the URL Encode tool
URL encoding has just enough rules to go wrong in generated code. A space can be %20 or + depending on where it appears. encodeURI and encodeURIComponent disagree about &, = and /. Non-ASCII characters become one %XX per UTF-8 byte, so é is two escapes and an emoji is four. A model writing a redirect URL or decoding a tracking link from memory usually gets the common case right and one of these details wrong.
The devtoolbox.cc MCP server includes url, a tool that encodes, decodes and parses URLs with the platform’s own URL implementation. It’s the logic behind two tools on this site, the URL encoder and decoder and the URL parser. Installation is on the MCP page.
What the tool does
The mode argument picks one of three jobs.
encode percent-encodes text. Three encodings are available:
encoding |
Behaves like | Use it for |
|---|---|---|
component |
encodeURIComponent (default) |
One query value or path segment |
rfc3986 |
encodeURIComponent, plus !'()* |
APIs and OAuth signatures that follow RFC 3986 strictly |
uri |
encodeURI |
A whole URL, keeping :/?#&= as they are |
decode reverses percent-encoding and reports malformed sequences such as a lone % or invalid UTF-8 instead of guessing.
parse splits an absolute URL into protocol, credentials, host, port, path, fragment and the list of query parameters, each decoded, with repeated names kept in order.
With spaces_as_plus, encoding and decoding follow HTML form rules (application/x-www-form-urlencoded): a space is +, and a literal plus is %2B. With per_line, each line is handled separately, which is handy for a list of values.
Arguments
| Argument | Type | Meaning |
|---|---|---|
mode |
"encode", "decode" or "parse" |
Required. |
text |
string | The text, encoded string or URL. Required. |
encoding |
"component", "rfc3986", "uri" |
For encode. Default "component". |
spaces_as_plus |
boolean | Form encoding: space ↔ +, plus ↔ %2B. |
per_line |
boolean | Encode or decode each line on its own. |
Examples
These examples were run against the real tool. A query value with reserved characters and non-ASCII text:
{ "mode": "encode", "text": "price < 10 & café/bar" }
price%20%3C%2010%20%26%20caf%C3%A9%2Fbar
A whole URL keeps its structure with uri, and only the unsafe parts are escaped:
{ "mode": "encode", "text": "https://example.com/search?q=café au lait&page=2", "encoding": "uri" }
https://example.com/search?q=caf%C3%A9%20au%20lait&page=2
Form encoding, where a literal plus has to stay distinguishable from a space:
{ "mode": "encode", "text": "C++ & C#", "spaces_as_plus": true }
C%2B%2B+%26+C%23
{ "mode": "decode", "text": "C%2B%2B+%26+C%23", "spaces_as_plus": true }
C++ & C#
Without spaces_as_plus, a + is decoded as a plus sign, which is correct for paths and for APIs that don’t use form encoding. Decoding errors say where the problem is:
{ "mode": "decode", "text": "100%25 done, 50% left" }
Malformed percent-encoding at position 16
Parsing a URL with credentials, a port, a repeated parameter and an empty one:
{
"mode": "parse",
"text": "https://ci:token@builds.example.com:8443/api/v2/runs?branch=main&tag=a&tag=b&debug=#latest"
}
{
"href": "https://ci:token@builds.example.com:8443/api/v2/runs?branch=main&tag=a&tag=b&debug=#latest",
"protocol": "https:",
"username": "ci",
"password": "token",
"hostname": "builds.example.com",
"port": "8443",
"pathname": "/api/v2/runs",
"hash": "#latest",
"params": [
[
"branch",
"main"
],
[
"tag",
"a"
],
[
"tag",
"b"
],
[
"debug",
""
]
]
}
The query parameters come back as a list of pairs, not an object, so tag=a&tag=b keeps both values and debug with an empty value isn’t lost.
A URL inside a URL
Redirect and callback parameters carry a whole URL as one query value. That value must be encoded with component, so that its own ?, & and = don’t merge with the outer URL’s:
{ "mode": "encode", "text": "https://app.example.com/cb?state=xyz&next=/home" }
https%3A%2F%2Fapp.example.com%2Fcb%3Fstate%3Dxyz%26next%3D%2Fhome
With uri encoding, the reserved characters stay as they are:
{ "mode": "encode", "text": "https://app.example.com/cb?state=xyz&next=/home", "encoding": "uri" }
https://app.example.com/cb?state=xyz&next=/home
Put that second form after ?redirect= and the server sees redirect=https://app.example.com/cb?state=xyz and a separate next parameter. It’s a classic source of broken OAuth flows.
Double encoding
Logs and proxies sometimes encode a value twice. A space becomes %20, and then the % itself becomes %25, so the log shows %2520. Decoding once gives the intermediate form:
{ "mode": "decode", "text": "report%2520final.pdf" }
report%20final.pdf
A second decode gives report final.pdf. If a value still contains %25 after one decode, it was encoded twice somewhere along the way, which usually points at a client or proxy that encodes an already encoded URL.
Things to ask your assistant
- “Decode the
redirect_uriparameter in this OAuth URL and tell me where it sends the user.” - “Build the search URL for ‘Zürich Hauptbahnhof’ with the right encoding for the
qparameter.” - “Parse every URL in
access.loglines 1–50 and list the distinct values of theutm_sourceparameter.” - “Encode each line of
keywords.txtas a query value.”
For working on one URL by hand, the URL parser shows the parts and lets you edit query parameters in a table, and the URL encoder converts both ways as you type.
Why exact encoding matters
An encoding mistake is rarely visible. a+b in a query string arrives at the server as “a b” if the client meant a literal plus. A redirect URL encoded with encodeURI instead of encodeURIComponent leaks its own & parameters into the outer URL. An OAuth signature computed over a string encoded slightly differently from the server’s version simply fails, with no hint why. These are exactly the details a tool gets right every time, and the reason the agent should call one instead of retyping escapes.
The URL encoding article covers the rules in more depth.
Install
url is part of the devtoolbox.cc MCP server. It runs locally and doesn’t make network requests; parsing a URL never fetches it. Setup for Claude Desktop, Claude Code, Cursor and VS Code is on the MCP install page.