# Directory Structure
```
├── .gitignore
├── .idea
│ ├── .gitignore
│ ├── inspectionProfiles
│ │ └── profiles_settings.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── new_relic.iml
│ └── vcs.xml
├── .python-version
├── app.py
├── pyproject.toml
├── README.md
└── uv.lock
```
# Files
--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------
```
1 | 3.13
2 |
```
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | # Python-generated files
2 | __pycache__/
3 | *.py[oc]
4 | build/
5 | dist/
6 | wheels/
7 | *.egg-info
8 |
9 | # Virtual environments
10 | .venv
11 | ./.gitignore
12 |
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
1 | [](https://mseep.ai/app/ivlad003-mcp-newrelic)
2 |
3 | # New Relic MCP Server
4 |
5 | A simple Model Context Protocol (MCP) server for querying New Relic logs using NRQL queries. This server enables Large Language Models (LLMs) like Claude to interact with your New Relic data.
6 |
7 | ## Features
8 |
9 | - Query New Relic logs and metrics using NRQL
10 | - Detailed error logging
11 | - Easy integration with Claude Desktop
12 | - Human-readable output formatting
13 | - Configurable New Relic account ID
14 |
15 | ## Setup Instructions
16 |
17 | ### Prerequisites
18 |
19 | - Python 3.10 or higher
20 | - New Relic account and API key
21 | - Claude Desktop application
22 |
23 | ### Installation Steps
24 |
25 | 1. Install `uv` package manager:
26 | ```bash
27 | # On macOS/Linux
28 | curl -LsSf https://astral.sh/uv/install.sh | sh
29 |
30 | # On Windows (PowerShell)
31 | powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
32 | ```
33 |
34 | 2. Create and setup project:
35 | ```bash
36 | # Create directory
37 | mkdir newrelic-mcp
38 | cd newrelic-mcp
39 |
40 | # Create virtual environment
41 | uv venv
42 |
43 | # Activate virtual environment
44 | source .venv/bin/activate # On Unix/macOS
45 | .venv\Scripts\activate # On Windows
46 |
47 | # Install dependencies
48 | uv pip install "mcp[cli]" httpx
49 | ```
50 |
51 | 3. Create server file `newrelic_logs_server.py` with the provided code.
52 |
53 | 4. Configure your environment variables:
54 | ```bash
55 | # On Unix/macOS
56 | export NEW_RELIC_API_KEY="your-api-key-here"
57 | export NEW_RELIC_ACCOUNT_ID="your-account-id-here"
58 |
59 | # On Windows (CMD)
60 | set NEW_RELIC_API_KEY=your-api-key-here
61 | set NEW_RELIC_ACCOUNT_ID=your-account-id-here
62 |
63 | # On Windows (PowerShell)
64 | $env:NEW_RELIC_API_KEY = "your-api-key-here"
65 | $env:NEW_RELIC_ACCOUNT_ID = "your-account-id-here"
66 | ```
67 |
68 | ### Claude Desktop Integration
69 |
70 | Configure Claude Desktop by editing your configuration file:
71 |
72 | - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
73 | - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
74 |
75 | Add the following configuration:
76 | ```json
77 | {
78 | "mcpServers": {
79 | "newrelic": {
80 | "command": "uv",
81 | "args": [
82 | "--directory",
83 | "/absolute/path/to/newrelic-mcp",
84 | "run",
85 | "newrelic_logs_server.py"
86 | ],
87 | "env": {
88 | "NEW_RELIC_API_KEY": "your-api-key-here",
89 | "NEW_RELIC_ACCOUNT_ID": "your-account-id-here"
90 | }
91 | }
92 | }
93 | }
94 | ```
95 |
96 | ## Usage
97 |
98 | ### Example NRQL Queries
99 |
100 | 1. Basic Transaction Query:
101 | ```sql
102 | SELECT * FROM Transaction SINCE 1 hour ago
103 | ```
104 |
105 | 2. Error Analysis:
106 | ```sql
107 | SELECT * FROM Transaction WHERE error IS TRUE SINCE 1 hour ago LIMIT 10
108 | ```
109 |
110 | 3. Performance Analysis:
111 | ```sql
112 | SELECT average(duration) FROM Transaction FACET name ORDER BY average(duration) DESC LIMIT 5
113 | ```
114 |
115 | ### Example Claude Prompts
116 |
117 | You can ask Claude questions like:
118 | - "Show me all transactions from the last hour"
119 | - "Are there any errors in our application?"
120 | - "What are our slowest endpoints?"
121 |
122 | ## Debugging
123 |
124 | ### Viewing Logs
125 |
126 | ```bash
127 | # On macOS/Linux
128 | tail -f ~/Library/Logs/Claude/mcp-server-newrelic.log
129 |
130 | # On Windows
131 | type %APPDATA%\Claude\logs\mcp-server-newrelic.log
132 | ```
133 |
134 | ### Testing with MCP Inspector
135 |
136 | Test your server functionality using:
137 | ```bash
138 | npx @modelcontextprotocol/inspector uv run newrelic_logs_server.py
139 | ```
140 |
141 | ### Common Issues
142 |
143 | 1. Authentication Errors:
144 | - Check if NEW_RELIC_API_KEY is set correctly
145 | - Verify API key has correct permissions
146 | - Ensure API key is valid
147 |
148 | 2. Query Errors:
149 | - Verify NRQL syntax
150 | - Check account ID in code matches your account
151 | - Ensure queried data exists in the time range
152 |
153 | 3. Connection Issues:
154 | - Check network connectivity
155 | - Verify GraphQL endpoint is accessible
156 | - Ensure no firewalls are blocking connections
157 |
158 | ## Security Notes
159 |
160 | - Never commit API keys to version control
161 | - Use environment variables for sensitive data
162 | - Keep dependencies updated
163 | - Monitor query patterns and access logs
164 |
165 | ## Development
166 |
167 | ### Local Testing
168 |
169 | 1. Set environment variables:
170 | ```bash
171 | export NEW_RELIC_API_KEY="your-api-key-here"
172 | export NEW_RELIC_ACCOUNT_ID="your-account-id-here"
173 | ```
174 |
175 | 2. Run the server:
176 | ```bash
177 | uv run newrelic_logs_server.py
178 | ```
179 |
180 | ### Code Structure
181 |
182 | The server implements:
183 | - Single NRQL query tool
184 | - Configurable New Relic account ID
185 | - Comprehensive error handling
186 | - Detailed logging
187 | - Response formatting
188 |
189 | ### Testing Changes
190 |
191 | 1. Modify code as needed
192 | 2. Test with MCP Inspector
193 | 3. Restart Claude Desktop to apply changes
194 |
195 | ## Troubleshooting Guide
196 |
197 | 1. Server Not Starting:
198 | - Check Python version
199 | - Verify all dependencies are installed
200 | - Ensure virtual environment is activated
201 |
202 | 2. Query Not Working:
203 | - Check logs for detailed error messages
204 | - Verify NRQL syntax
205 | - Ensure data exists in queried time range
206 |
207 | 3. Claude Not Connecting:
208 | - Verify configuration file syntax
209 | - Check paths are absolute
210 | - Restart Claude Desktop
211 |
212 | ## Contributing
213 |
214 | 1. Fork the repository
215 | 2. Create a feature branch
216 | 3. Submit a pull request
217 |
218 | ## License
219 |
220 | This project is licensed under the MIT License.
221 |
222 | ## Support
223 |
224 | If you encounter issues:
225 | 1. Check the logs
226 | 2. Review common issues section
227 | 3. Test with MCP Inspector
228 | 4. File an issue on GitHub
```
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project version="4">
3 | <component name="VcsDirectoryMappings">
4 | <mapping directory="" vcs="Git" />
5 | </component>
6 | </project>
```
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
```
1 | <component name="InspectionProjectProfileManager">
2 | <settings>
3 | <option name="USE_PROJECT_PROFILE" value="false" />
4 | <version value="1.0" />
5 | </settings>
6 | </component>
```
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
```toml
1 | [project]
2 | name = "mcp-newrelic"
3 | version = "0.1.0"
4 | description = "Add your description here"
5 | readme = "README.md"
6 | requires-python = ">=3.13"
7 | dependencies = [
8 | "httpx>=0.28.1",
9 | "mcp[cli]>=1.2.0",
10 | "pydantic>=2.10.5",
11 | ]
12 |
```
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project version="4">
3 | <component name="ProjectModuleManager">
4 | <modules>
5 | <module fileurl="file://$PROJECT_DIR$/.idea/new_relic.iml" filepath="$PROJECT_DIR$/.idea/new_relic.iml" />
6 | </modules>
7 | </component>
8 | </project>
```
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
```
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <project version="4">
3 | <component name="Black">
4 | <option name="sdkName" value="Python 3.13 (new_relic)" />
5 | </component>
6 | <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (new_relic)" project-jdk-type="Python SDK" />
7 | </project>
```
--------------------------------------------------------------------------------
/app.py:
--------------------------------------------------------------------------------
```python
1 | import os
2 | import httpx
3 | from mcp.server.fastmcp import FastMCP
4 | import logging
5 |
6 | # Initialize FastMCP server
7 | mcp = FastMCP("newrelic-logs")
8 |
9 | # Configure logging
10 | logging.basicConfig(level=logging.DEBUG)
11 | logger = logging.getLogger(__name__)
12 |
13 | # Constants
14 | NR_GRAPHQL_URL = "https://api.newrelic.com/graphql"
15 | DEFAULT_ACCOUNT_ID = os.getenv("NEW_RELIC_ACCOUNT_ID", "1892029")
16 |
17 | @mcp.tool()
18 | async def query_logs(query: str, account_id: str = DEFAULT_ACCOUNT_ID) -> str:
19 | """Query New Relic logs using NRQL.
20 |
21 | Args:
22 | query: NRQL query string (e.g., "SELECT * FROM Transaction")
23 | account_id: New Relic account ID (default from env var)
24 | """
25 | graphql_query = f"""
26 | {{
27 | actor {{
28 | account(id: {account_id}) {{
29 | nrql(query: "{query}") {{
30 | results
31 | }}
32 | }}
33 | }}
34 | }}
35 | """
36 |
37 | headers = {
38 | "Content-Type": "application/json",
39 | "API-Key": os.getenv("NEW_RELIC_API_KEY")
40 | }
41 |
42 | payload = {
43 | "query": graphql_query
44 | }
45 |
46 | try:
47 | async with httpx.AsyncClient() as client:
48 | response = await client.post(
49 | NR_GRAPHQL_URL,
50 | headers=headers,
51 | json=payload
52 | )
53 | response.raise_for_status()
54 | result = response.json()
55 |
56 | # Log the full response content
57 | logger.debug("Response JSON: %s", result)
58 |
59 | # Check for errors in the response
60 | if "errors" in result:
61 | logger.error("GraphQL errors: %s", result["errors"])
62 | return f"GraphQL errors: {result['errors']}"
63 |
64 | # Extract logs from response
65 | data = result.get("data")
66 | if data is None:
67 | logger.error("No 'data' field in response")
68 | return "Error: No 'data' field in response"
69 |
70 | account = data.get("actor", {}).get("account")
71 | if account is None:
72 | logger.error("No 'account' field in 'actor'")
73 | return "Error: No 'account' field in 'actor'"
74 |
75 | nrql = account.get("nrql")
76 | if nrql is None:
77 | logger.error("No 'nrql' field in 'account'")
78 | return "Error: No 'nrql' field in 'account'"
79 |
80 | logs = nrql.get("results", [])
81 |
82 | # Format the logs into a readable string
83 | formatted_logs = []
84 | for log in logs:
85 | formatted_logs.append("---\n" + "\n".join(f"{k}: {v}" for k, v in log.items()))
86 |
87 | return "\n".join(formatted_logs) if formatted_logs else "No logs found"
88 | except Exception as e:
89 | logger.error("Error querying logs: %s", str(e))
90 | return f"Error querying logs: {str(e)}"
91 |
92 |
93 | if __name__ == "__main__":
94 | mcp.run()
```