ipinfo-mcp-server 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ipinfo_mcp_server-0.2.3/.cursor-plugin/marketplace.json +17 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.mcpbignore +2 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/PKG-INFO +14 -13
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/README.md +13 -12
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/manifest.json +1 -1
- ipinfo_mcp_server-0.2.3/plugins/ipinfo/.cursor-plugin/plugin.json +20 -0
- ipinfo_mcp_server-0.2.3/plugins/ipinfo/README.md +47 -0
- ipinfo_mcp_server-0.2.3/plugins/ipinfo/assets/logo-dark.png +0 -0
- ipinfo_mcp_server-0.2.3/plugins/ipinfo/assets/logo.png +0 -0
- ipinfo_mcp_server-0.2.3/plugins/ipinfo/mcp.json +9 -0
- ipinfo_mcp_server-0.2.3/plugins/ipinfo/plugin.json +109 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/pyproject.toml +1 -1
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/server.json +2 -2
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/server.py +10 -3
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/uv.lock +1 -1
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.dockerignore +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.env.example +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/dependabot.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/build.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/codeql.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/mcp-registry.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/pypi.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/release.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/scorecard.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.github/workflows/test.yml +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/.gitignore +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/CONTRIBUTING.md +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/Dockerfile +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/LICENSE.txt +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/SECURITY.md +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/assets/logo-dark.png +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/assets/logo-light.png +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/__init__.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/__main__.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/auth.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/cache.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/client.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/errors.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/landing.html +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/logging.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/pagination.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/params.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/__init__.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/asn.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/geolocate.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/lookup.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/privacy.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/quota.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/tools/resproxy.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/types.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/src/ipinfo_mcp/validation.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/__init__.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/conftest.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/integration/__init__.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/integration/test_client.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/test_auth.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/test_cache.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/test_client.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/test_pagination.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/test_validation.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/__init__.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/test_asn.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/test_geolocate.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/test_lookup.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/test_privacy.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/test_quota.py +0 -0
- {ipinfo_mcp_server-0.2.2 → ipinfo_mcp_server-0.2.3}/tests/tools/test_resproxy.py +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ipinfo",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "IPinfo",
|
|
5
|
+
"email": "support@ipinfo.io"
|
|
6
|
+
},
|
|
7
|
+
"metadata": {
|
|
8
|
+
"description": "Official IPinfo plugins"
|
|
9
|
+
},
|
|
10
|
+
"plugins": [
|
|
11
|
+
{
|
|
12
|
+
"name": "ipinfo",
|
|
13
|
+
"source": "./plugins/ipinfo",
|
|
14
|
+
"description": "IP address intelligence from IPinfo: geolocation, network ownership, and VPN, proxy, Tor, and residential proxy detection."
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ipinfo-mcp-server
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Official IPinfo MCP Server - IP intelligence tools for AI assistants
|
|
5
5
|
Author-email: IPinfo <support@ipinfo.io>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -139,18 +139,19 @@ Takes no parameters. Returns `token` (omitted when connected with OAuth), `reque
|
|
|
139
139
|
|
|
140
140
|
The server is configured through environment variables:
|
|
141
141
|
|
|
142
|
-
| Variable
|
|
143
|
-
|
|
|
144
|
-
| `IPINFO_TOKEN`
|
|
145
|
-
| `IPINFO_API_BASE_URL`
|
|
146
|
-
| `IPINFO_LEGACY_BASE_URL`
|
|
147
|
-
| `IPINFO_CACHE_TTL`
|
|
148
|
-
| `IPINFO_TRANSPORT`
|
|
149
|
-
| `HOST`
|
|
150
|
-
| `PORT`
|
|
151
|
-
| `IPINFO_OAUTH_ISSUER`
|
|
152
|
-
| `IPINFO_MCP_RESOURCE_URL`
|
|
153
|
-
| `IPINFO_OAUTH_JWKS_URI`
|
|
142
|
+
| Variable | Default | Description |
|
|
143
|
+
| ------------------------------ | -------------------------------- | ------------------------------------------------------------------------------------- |
|
|
144
|
+
| `IPINFO_TOKEN` | | API token (stdio transport; over HTTP the token comes from the request) |
|
|
145
|
+
| `IPINFO_API_BASE_URL` | `https://api.ipinfo.io` | Base URL for `api.ipinfo.io` endpoints |
|
|
146
|
+
| `IPINFO_LEGACY_BASE_URL` | `https://ipinfo.io` | Base URL for legacy `ipinfo.io` endpoints (e.g. `/me`) |
|
|
147
|
+
| `IPINFO_CACHE_TTL` | `3600` | Seconds a cached IP result stays fresh |
|
|
148
|
+
| `IPINFO_TRANSPORT` | `stdio` | Transport type (`stdio` or `http`) |
|
|
149
|
+
| `HOST` | `0.0.0.0` | HTTP host (only for `http` transport) |
|
|
150
|
+
| `PORT` | `8000` | HTTP port (only for `http` transport) |
|
|
151
|
+
| `IPINFO_OAUTH_ISSUER` | | OAuth issuer whose access tokens are accepted; OAuth is off when unset |
|
|
152
|
+
| `IPINFO_MCP_RESOURCE_URL` | | Public URL of this server, required with `IPINFO_OAUTH_ISSUER` |
|
|
153
|
+
| `IPINFO_OAUTH_JWKS_URI` | `<issuer>/.well-known/jwks.json` | Where the issuer publishes its signing keys |
|
|
154
|
+
| `IPINFO_OPENAI_APPS_CHALLENGE` | | Token served at `/.well-known/openai-apps-challenge` for OpenAI's domain verification |
|
|
154
155
|
|
|
155
156
|
With the `http` transport, each request authenticates with its own `Authorization: Bearer <token>` header.
|
|
156
157
|
|
|
@@ -122,18 +122,19 @@ Takes no parameters. Returns `token` (omitted when connected with OAuth), `reque
|
|
|
122
122
|
|
|
123
123
|
The server is configured through environment variables:
|
|
124
124
|
|
|
125
|
-
| Variable
|
|
126
|
-
|
|
|
127
|
-
| `IPINFO_TOKEN`
|
|
128
|
-
| `IPINFO_API_BASE_URL`
|
|
129
|
-
| `IPINFO_LEGACY_BASE_URL`
|
|
130
|
-
| `IPINFO_CACHE_TTL`
|
|
131
|
-
| `IPINFO_TRANSPORT`
|
|
132
|
-
| `HOST`
|
|
133
|
-
| `PORT`
|
|
134
|
-
| `IPINFO_OAUTH_ISSUER`
|
|
135
|
-
| `IPINFO_MCP_RESOURCE_URL`
|
|
136
|
-
| `IPINFO_OAUTH_JWKS_URI`
|
|
125
|
+
| Variable | Default | Description |
|
|
126
|
+
| ------------------------------ | -------------------------------- | ------------------------------------------------------------------------------------- |
|
|
127
|
+
| `IPINFO_TOKEN` | | API token (stdio transport; over HTTP the token comes from the request) |
|
|
128
|
+
| `IPINFO_API_BASE_URL` | `https://api.ipinfo.io` | Base URL for `api.ipinfo.io` endpoints |
|
|
129
|
+
| `IPINFO_LEGACY_BASE_URL` | `https://ipinfo.io` | Base URL for legacy `ipinfo.io` endpoints (e.g. `/me`) |
|
|
130
|
+
| `IPINFO_CACHE_TTL` | `3600` | Seconds a cached IP result stays fresh |
|
|
131
|
+
| `IPINFO_TRANSPORT` | `stdio` | Transport type (`stdio` or `http`) |
|
|
132
|
+
| `HOST` | `0.0.0.0` | HTTP host (only for `http` transport) |
|
|
133
|
+
| `PORT` | `8000` | HTTP port (only for `http` transport) |
|
|
134
|
+
| `IPINFO_OAUTH_ISSUER` | | OAuth issuer whose access tokens are accepted; OAuth is off when unset |
|
|
135
|
+
| `IPINFO_MCP_RESOURCE_URL` | | Public URL of this server, required with `IPINFO_OAUTH_ISSUER` |
|
|
136
|
+
| `IPINFO_OAUTH_JWKS_URI` | `<issuer>/.well-known/jwks.json` | Where the issuer publishes its signing keys |
|
|
137
|
+
| `IPINFO_OPENAI_APPS_CHALLENGE` | | Token served at `/.well-known/openai-apps-challenge` for OpenAI's domain verification |
|
|
137
138
|
|
|
138
139
|
With the `http` transport, each request authenticates with its own `Authorization: Bearer <token>` header.
|
|
139
140
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": "0.4",
|
|
3
3
|
"name": "ipinfo-mcp-server",
|
|
4
4
|
"display_name": "IPinfo",
|
|
5
|
-
"version": "0.2.
|
|
5
|
+
"version": "0.2.3",
|
|
6
6
|
"description": "IP address intelligence tools: geolocation, ASN, privacy detection, residential proxy checks, and more.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "IPinfo",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ipinfo",
|
|
3
|
+
"displayName": "IPinfo",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "IP address intelligence from IPinfo: geolocation, network ownership, and VPN, proxy, Tor, and residential proxy detection.",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "IPinfo",
|
|
8
|
+
"email": "support@ipinfo.io"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://ipinfo.io/developers/mcp-server",
|
|
11
|
+
"repository": "https://github.com/ipinfo/mcp",
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"keywords": ["ip", "geolocation", "asn", "vpn", "proxy", "tor", "residential-proxy", "security"],
|
|
14
|
+
"logo": "assets/logo.png",
|
|
15
|
+
"mcpServers": {
|
|
16
|
+
"ipinfo": {
|
|
17
|
+
"url": "https://mcp.ipinfo.io/"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# IPinfo plugin
|
|
2
|
+
|
|
3
|
+
Connects your AI assistant to the hosted [IPinfo MCP Server](https://github.com/ipinfo/mcp), so it can answer questions about IP addresses with [IPinfo](https://ipinfo.io) data: where an IP is located, which company or network it belongs to, and whether it's a VPN, proxy, Tor exit node, or residential proxy.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
Install the plugin, then sign in with your IPinfo account when your client asks. There is nothing else to configure: the plugin connects to `https://mcp.ipinfo.io/` and authenticates through OAuth.
|
|
8
|
+
|
|
9
|
+
You need an IPinfo account. Sign up for free at [ipinfo.io/signup](https://ipinfo.io/signup).
|
|
10
|
+
|
|
11
|
+
## Tools
|
|
12
|
+
|
|
13
|
+
| Tool | Description | Plan requirement |
|
|
14
|
+
| -------------------------------- | ----------------------------------------------------------------- | ------------------------------------- |
|
|
15
|
+
| `ipinfo_lookup` | Full IP data: geolocation, network, and metadata | Any; `detailed: true` needs Core/Plus |
|
|
16
|
+
| `ipinfo_geolocate` | Geographic location | Any; `detailed: true` needs Core/Plus |
|
|
17
|
+
| `ipinfo_asn` | Autonomous system (network ownership) | Any; `detailed: true` needs Core/Plus |
|
|
18
|
+
| `ipinfo_check_privacy` | VPN, proxy, relay, Tor, hosting, anycast, mobile, satellite flags | Paid plan |
|
|
19
|
+
| `ipinfo_check_residential_proxy` | Residential proxy detection | Residential Proxy access |
|
|
20
|
+
| `ipinfo_quota` | API usage and remaining quota | Any |
|
|
21
|
+
|
|
22
|
+
All tools are read-only. Try asking:
|
|
23
|
+
|
|
24
|
+
- "Where is the IP address 8.8.8.8 located?"
|
|
25
|
+
- "Is 185.220.101.1 a VPN, proxy, or Tor exit node?"
|
|
26
|
+
- "Which company operates the network for 1.1.1.1?"
|
|
27
|
+
|
|
28
|
+
## Support
|
|
29
|
+
|
|
30
|
+
- Documentation: [ipinfo.io/developers/mcp-server](https://ipinfo.io/developers/mcp-server)
|
|
31
|
+
- Support: [support.ipinfo.io](https://support.ipinfo.io/hc/en-us) or support@ipinfo.io
|
|
32
|
+
- Privacy policy: [ipinfo.io/privacy-policy](https://ipinfo.io/privacy-policy)
|
|
33
|
+
|
|
34
|
+
## Packaging
|
|
35
|
+
|
|
36
|
+
This folder is both an [Agent Plugins](https://agent-plugins.org) package and a Cursor plugin:
|
|
37
|
+
|
|
38
|
+
- `plugin.json` and `mcp.json` are the portable package. OpenAI-specific listing and review details live under `extensions.com.openai` in `plugin.json`.
|
|
39
|
+
- `.cursor-plugin/plugin.json` adds the Cursor listing details, such as the logo. The repository's `.cursor-plugin/marketplace.json` points Cursor at this folder.
|
|
40
|
+
|
|
41
|
+
To build the ZIP for the OpenAI plugin portal, run this from the `plugins` directory. It leaves out the Cursor manifest:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
zip -r -X ipinfo-plugin.zip ipinfo -x '*.DS_Store' 'ipinfo/.cursor-plugin/*'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Bump `version` in both manifests before every new upload.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
|
+
"name": "ipinfo",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "IP address intelligence from IPinfo: geolocation, network ownership, and VPN, proxy, Tor, and residential proxy detection.",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "IPinfo",
|
|
8
|
+
"email": "support@ipinfo.io",
|
|
9
|
+
"url": "https://ipinfo.io"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://ipinfo.io/developers/mcp-server",
|
|
12
|
+
"repository": "https://github.com/ipinfo/mcp",
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"ip",
|
|
16
|
+
"geolocation",
|
|
17
|
+
"asn",
|
|
18
|
+
"vpn",
|
|
19
|
+
"proxy",
|
|
20
|
+
"tor",
|
|
21
|
+
"residential-proxy",
|
|
22
|
+
"security"
|
|
23
|
+
],
|
|
24
|
+
"extensions": {
|
|
25
|
+
"com.openai": {
|
|
26
|
+
"interface": {
|
|
27
|
+
"displayName": "IPinfo",
|
|
28
|
+
"shortDescription": "IP geolocation and privacy",
|
|
29
|
+
"longDescription": "Look up IP addresses with IPinfo data. Find where an IP is located, down to the city, region, coordinates, timezone, and postal code. See which company or network owns it, with its ASN, organization name, domain, and network type. Check whether it belongs to a VPN, proxy, relay, or Tor exit node, whether it is a known residential proxy, and whether it is a hosting, anycast, mobile, or satellite address. You can also check your IPinfo API usage and remaining quota.\n\nUseful for security and fraud investigations, log and traffic analysis, and any question about where traffic comes from. Lookups accept many IPs at once, IPv4 or IPv6.\n\nSign in with your IPinfo account to connect. Every account includes country, continent, and ASN data. City-level geolocation, privacy detection, and residential proxy detection are available when your IPinfo plan includes them. Private, reserved, and bogon addresses aren't looked up. All tools are read-only and never change your account.",
|
|
30
|
+
"developerName": "IPinfo",
|
|
31
|
+
"category": "Data & Analytics",
|
|
32
|
+
"capabilities": [
|
|
33
|
+
"Geolocate IP addresses",
|
|
34
|
+
"Identify network owners and ASNs",
|
|
35
|
+
"Detect VPNs, proxies, relays, and Tor",
|
|
36
|
+
"Detect residential proxies",
|
|
37
|
+
"Check API usage and quota"
|
|
38
|
+
],
|
|
39
|
+
"websiteURL": "https://ipinfo.io",
|
|
40
|
+
"supportURL": "https://support.ipinfo.io/",
|
|
41
|
+
"privacyPolicyURL": "https://ipinfo.io/privacy-policy",
|
|
42
|
+
"termsOfServiceURL": "https://ipinfo.io/terms-of-service",
|
|
43
|
+
"defaultPrompt": [
|
|
44
|
+
"Where is the IP address 8.8.8.8 located?",
|
|
45
|
+
"Is 185.220.101.1 a VPN, proxy, or Tor exit node?",
|
|
46
|
+
"Which company operates the network for 1.1.1.1?"
|
|
47
|
+
],
|
|
48
|
+
"logo": "./assets/logo.png",
|
|
49
|
+
"logoDark": "./assets/logo-dark.png",
|
|
50
|
+
"composerIcon": "./assets/logo.png",
|
|
51
|
+
"composerIconDark": "./assets/logo-dark.png"
|
|
52
|
+
},
|
|
53
|
+
"review": {
|
|
54
|
+
"test_cases": {
|
|
55
|
+
"positive": [
|
|
56
|
+
{
|
|
57
|
+
"description": "Geolocate an IP address",
|
|
58
|
+
"prompt": "Where is the IP address 8.8.8.8 located? Include the city and timezone.",
|
|
59
|
+
"tools_triggered": "ipinfo_geolocate",
|
|
60
|
+
"expected_behavior": "Reports that 8.8.8.8 is in Mountain View, California, United States, with the America/Los_Angeles timezone."
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"description": "Identify who owns a network",
|
|
64
|
+
"prompt": "Which company operates the network for 1.1.1.1?",
|
|
65
|
+
"tools_triggered": "ipinfo_asn",
|
|
66
|
+
"expected_behavior": "Reports that 1.1.1.1 belongs to AS13335, Cloudflare, Inc. (cloudflare.com)."
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"description": "Detect anonymity services",
|
|
70
|
+
"prompt": "Is 185.220.101.1 a VPN, proxy, or Tor exit node?",
|
|
71
|
+
"tools_triggered": "ipinfo_check_privacy",
|
|
72
|
+
"expected_behavior": "Reports that 185.220.101.1 is anonymous and flagged as a Tor exit node, listing which of the VPN, proxy, relay, and Tor flags are set."
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"description": "Check for a residential proxy",
|
|
76
|
+
"prompt": "Is 8.8.8.8 a residential proxy?",
|
|
77
|
+
"tools_triggered": "ipinfo_check_residential_proxy",
|
|
78
|
+
"expected_behavior": "Reports that 8.8.8.8 is not a known residential proxy."
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"description": "Check API usage",
|
|
82
|
+
"prompt": "How many IPinfo API requests have I used this month, and how many do I have left?",
|
|
83
|
+
"tools_triggered": "ipinfo_quota",
|
|
84
|
+
"expected_behavior": "Reports the requests used today and this month, the plan limit, and the remaining requests for the connected account."
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"negative": [
|
|
88
|
+
{
|
|
89
|
+
"description": "Changing firewall or network settings is out of scope; the plugin is read-only and should explain it can't block addresses.",
|
|
90
|
+
"prompt": "Block the IP address 203.0.113.5 on my firewall."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"description": "IP data doesn't identify people; the plugin should decline to find a person's identity or home address.",
|
|
94
|
+
"prompt": "Find the name and home address of the person using the IP 8.8.8.8."
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"description": "The request has nothing to do with IP addresses, so no IPinfo tool should be called.",
|
|
98
|
+
"prompt": "Write a Python function that sorts a list of numbers."
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"commerce": false
|
|
103
|
+
},
|
|
104
|
+
"publication": {
|
|
105
|
+
"release_notes": "Initial release: IP geolocation, network ownership, privacy and residential proxy detection, and API quota checks."
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.ipinfo/mcp",
|
|
4
4
|
"title": "IPinfo",
|
|
5
5
|
"description": "Official IPinfo MCP Server - IP intelligence tools for AI assistants",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.3",
|
|
7
7
|
"websiteUrl": "https://ipinfo.io",
|
|
8
8
|
"repository": {
|
|
9
9
|
"url": "https://github.com/ipinfo/mcp",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"registryType": "pypi",
|
|
27
27
|
"registryBaseUrl": "https://pypi.org",
|
|
28
28
|
"identifier": "ipinfo-mcp-server",
|
|
29
|
-
"version": "0.2.
|
|
29
|
+
"version": "0.2.3",
|
|
30
30
|
"runtimeHint": "uvx",
|
|
31
31
|
"transport": {
|
|
32
32
|
"type": "stdio"
|
|
@@ -10,7 +10,7 @@ from typing import TypedDict, cast
|
|
|
10
10
|
import uvicorn
|
|
11
11
|
from fastmcp import FastMCP
|
|
12
12
|
from fastmcp.server.auth import MultiAuth
|
|
13
|
-
from starlette.responses import HTMLResponse, JSONResponse
|
|
13
|
+
from starlette.responses import HTMLResponse, JSONResponse, PlainTextResponse
|
|
14
14
|
from starlette.types import ASGIApp, Receive, Scope, Send
|
|
15
15
|
|
|
16
16
|
from ipinfo_mcp.auth import create_auth
|
|
@@ -132,10 +132,13 @@ class LandingPageMiddleware:
|
|
|
132
132
|
|
|
133
133
|
MCP clients use POST or GET with Accept: text/event-stream,
|
|
134
134
|
so a plain GET with Accept: text/html is always a browser.
|
|
135
|
+
|
|
136
|
+
Also serves the token OpenAI checks to verify we own the domain, when one is set.
|
|
135
137
|
"""
|
|
136
138
|
|
|
137
|
-
def __init__(self, app: ASGIApp) -> None:
|
|
139
|
+
def __init__(self, app: ASGIApp, *, openai_apps_challenge: str | None = None) -> None:
|
|
138
140
|
self.app = app
|
|
141
|
+
self.openai_apps_challenge = openai_apps_challenge
|
|
139
142
|
|
|
140
143
|
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
|
|
141
144
|
if scope["type"] == "http" and scope["method"] == "GET":
|
|
@@ -144,6 +147,10 @@ class LandingPageMiddleware:
|
|
|
144
147
|
response = JSONResponse({"status": "ok", "version": SERVER_VERSION})
|
|
145
148
|
await response(scope, receive, send)
|
|
146
149
|
return
|
|
150
|
+
if path == "/.well-known/openai-apps-challenge" and self.openai_apps_challenge:
|
|
151
|
+
response = PlainTextResponse(self.openai_apps_challenge)
|
|
152
|
+
await response(scope, receive, send)
|
|
153
|
+
return
|
|
147
154
|
if path == "/":
|
|
148
155
|
headers = dict(cast(list[tuple[bytes, bytes]], scope.get("headers", [])))
|
|
149
156
|
accept = headers.get(b"accept", b"").decode()
|
|
@@ -160,7 +167,7 @@ def create_app() -> ASGIApp:
|
|
|
160
167
|
path="/",
|
|
161
168
|
stateless_http=True,
|
|
162
169
|
)
|
|
163
|
-
return LandingPageMiddleware(mcp_app)
|
|
170
|
+
return LandingPageMiddleware(mcp_app, openai_apps_challenge=os.environ.get("IPINFO_OPENAI_APPS_CHALLENGE"))
|
|
164
171
|
|
|
165
172
|
|
|
166
173
|
app = create_app()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|