Skip to main content
Glama
dwain-barnes

MCP Server Police UK

by dwain-barnes

get_street_level_outcomes

Retrieve street-level crime outcomes for any UK area by specifying latitude/longitude, a custom polygon, or a location ID. Filter results by month using the optional date parameter.

Instructions

Retrieve outcomes by lat/lng, custom polygon, or location ID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
latNoLatitude of the requested area
lngNoLongitude of the requested area
polyNoThe lat/lng pairs defining the boundary of the custom area
location_idNoThe ID of the location
dateNoLimit results to a specific month (YYYY-MM)

Implementation Reference

  • The handler function `getStreetLevelOutcomes` that executes the tool logic. It accepts lat/lng, poly, or location_id parameters, builds query params, and calls the police.uk API endpoint 'outcomes-at-location'.
    async function getStreetLevelOutcomes(args: any) {
      const { lat, lng, poly, location_id, date } = args;
      const params: Record<string, any> = {};
      
      if (date) params.date = date;
      if (location_id) {
        params.location_id = location_id;
      } else if (lat && lng) {
        params.lat = lat;
        params.lng = lng;
      } else if (poly) {
        params.poly = poly;
      } else {
        return [];
      }
      
      return await makeApiRequest('outcomes-at-location', params) || [];
    }
  • The input schema definition for 'get_street_level_outcomes', describing its parameters: lat, lng, poly, location_id, and date.
    {
      name: 'get_street_level_outcomes',
      description: 'Retrieve outcomes by lat/lng, custom polygon, or location ID',
      inputSchema: {
        type: 'object',
        properties: {
          lat: { type: 'number', description: 'Latitude of the requested area' },
          lng: { type: 'number', description: 'Longitude of the requested area' },
          poly: { type: 'string', description: 'The lat/lng pairs defining the boundary of the custom area' },
          location_id: { type: 'number', description: 'The ID of the location' },
          date: { type: 'string', description: 'Limit results to a specific month (YYYY-MM)' }
        }
      }
    },
  • src/index.ts:447-469 (registration)
    The tool function mapping that registers the name 'get_street_level_outcomes' to the `getStreetLevelOutcomes` handler function.
    const toolFunctions = {
      get_street_level_crimes: getStreetLevelCrimes,
      get_street_level_outcomes: getStreetLevelOutcomes,
      get_crimes_at_location: getCrimesAtLocation,
      get_crimes_no_location: getCrimesNoLocation,
      get_crime_categories: getCrimeCategories,
      get_last_updated: getLastUpdated,
      get_outcomes_for_crime: getOutcomesForCrime,
      get_list_of_forces: getListOfForces,
      get_force_details: getForceDetails,
      get_senior_officers: getSeniorOfficers,
      get_neighbourhoods: getNeighbourhoods,
      get_neighbourhood_details: getNeighbourhoodDetails,
      get_neighbourhood_boundary: getNeighbourhoodBoundary,
      get_neighbourhood_team: getNeighbourhoodTeam,
      get_neighbourhood_events: getNeighbourhoodEvents,
      get_neighbourhood_priorities: getNeighbourhoodPriorities,
      locate_neighbourhood: locateNeighbourhood,
      get_stop_searches_by_area: getStopSearchesByArea,
      get_stop_searches_by_location: getStopSearchesByLocation,
      get_stop_searches_no_location: getStopSearchesNoLocation,
      get_stop_searches_by_force: getStopSearchesByForce
    };
  • src/index.ts:22-269 (registration)
    The tools array registration (ListTools handler) where the tool name and schema are listed for the MCP server.
    // Define tool schemas
    const tools = [
      {
        name: 'get_street_level_crimes',
        description: 'Retrieve street-level crimes by lat/lng or custom polygon area',
        inputSchema: {
          type: 'object',
          properties: {
            lat: { type: 'number', description: 'Latitude of the requested crime area' },
            lng: { type: 'number', description: 'Longitude of the requested crime area' },
            poly: { type: 'string', description: 'The lat/lng pairs defining the boundary of the custom area' },
            date: { type: 'string', description: 'Limit results to a specific month (YYYY-MM)' },
            category: { type: 'string', description: 'The crime category', default: 'all-crime' }
          }
        }
      },
      {
        name: 'get_street_level_outcomes',
        description: 'Retrieve outcomes by lat/lng, custom polygon, or location ID',
        inputSchema: {
          type: 'object',
          properties: {
            lat: { type: 'number', description: 'Latitude of the requested area' },
            lng: { type: 'number', description: 'Longitude of the requested area' },
            poly: { type: 'string', description: 'The lat/lng pairs defining the boundary of the custom area' },
            location_id: { type: 'number', description: 'The ID of the location' },
            date: { type: 'string', description: 'Limit results to a specific month (YYYY-MM)' }
          }
        }
      },
      {
        name: 'get_crimes_at_location',
        description: 'Retrieve crimes at a specific location by ID or nearest to lat/lng',
        inputSchema: {
          type: 'object',
          properties: {
            lat: { type: 'number', description: 'Latitude of the requested crime area' },
            lng: { type: 'number', description: 'Longitude of the requested crime area' },
            location_id: { type: 'number', description: 'The ID of the location' },
            date: { type: 'string', description: 'Limit results to a specific month (YYYY-MM)' }
          }
        }
      },
      {
        name: 'get_crimes_no_location',
        description: 'Retrieve crimes that could not be mapped to a location',
        inputSchema: {
          type: 'object',
          properties: {
            category: { type: 'string', description: 'The category of the crimes' },
            force: { type: 'string', description: 'Specific police force' },
            date: { type: 'string', description: 'Limit results to a specific month (YYYY-MM)' }
          },
          required: ['category', 'force']
        }
      },
      {
        name: 'get_crime_categories',
        description: 'Retrieve valid crime categories for a given date',
        inputSchema: {
          type: 'object',
          properties: {
            date: { type: 'string', description: 'Specific month (YYYY-MM)' }
          }
        }
      },
      {
        name: 'get_last_updated',
        description: 'Retrieve the date when crime data was last updated',
        inputSchema: {
          type: 'object',
          properties: {}
        }
      },
      {
        name: 'get_outcomes_for_crime',
        description: 'Retrieve outcomes for a specific crime by persistent ID',
        inputSchema: {
          type: 'object',
          properties: {
            persistent_id: { type: 'string', description: 'The 64-character unique identifier for the crime' }
          },
          required: ['persistent_id']
        }
      },
      {
        name: 'get_list_of_forces',
        description: 'Retrieve a list of all police forces',
        inputSchema: {
          type: 'object',
          properties: {}
        }
      },
      {
        name: 'get_force_details',
        description: 'Retrieve details for a specific police force',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' }
          },
          required: ['force_id']
        }
      },
      {
        name: 'get_senior_officers',
        description: 'Retrieve senior officers for a specific police force',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' }
          },
          required: ['force_id']
        }
      },
      {
        name: 'get_neighbourhoods',
        description: 'Retrieve a list of neighbourhoods for a specific police force',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' }
          },
          required: ['force_id']
        }
      },
      {
        name: 'get_neighbourhood_details',
        description: 'Retrieve details for a specific neighbourhood within a force',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            neighbourhood_id: { type: 'string', description: 'The unique identifier for the neighbourhood' }
          },
          required: ['force_id', 'neighbourhood_id']
        }
      },
      {
        name: 'get_neighbourhood_boundary',
        description: 'Retrieve the boundary coordinates for a specific neighbourhood',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            neighbourhood_id: { type: 'string', description: 'The unique identifier for the neighbourhood' }
          },
          required: ['force_id', 'neighbourhood_id']
        }
      },
      {
        name: 'get_neighbourhood_team',
        description: 'Retrieve the team members for a specific neighbourhood',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            neighbourhood_id: { type: 'string', description: 'The unique identifier for the neighbourhood' }
          },
          required: ['force_id', 'neighbourhood_id']
        }
      },
      {
        name: 'get_neighbourhood_events',
        description: 'Retrieve events scheduled for a specific neighbourhood',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            neighbourhood_id: { type: 'string', description: 'The unique identifier for the neighbourhood' }
          },
          required: ['force_id', 'neighbourhood_id']
        }
      },
      {
        name: 'get_neighbourhood_priorities',
        description: 'Retrieve policing priorities for a specific neighbourhood',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            neighbourhood_id: { type: 'string', description: 'The unique identifier for the neighbourhood' }
          },
          required: ['force_id', 'neighbourhood_id']
        }
      },
      {
        name: 'locate_neighbourhood',
        description: 'Find the neighbourhood policing team for a given latitude and longitude',
        inputSchema: {
          type: 'object',
          properties: {
            lat: { type: 'number', description: 'Latitude of the location' },
            lng: { type: 'number', description: 'Longitude of the location' }
          },
          required: ['lat', 'lng']
        }
      },
      {
        name: 'get_stop_searches_by_area',
        description: 'Retrieve stop and searches within a 1-mile radius or custom area',
        inputSchema: {
          type: 'object',
          properties: {
            lat: { type: 'number', description: 'Latitude of the centre point' },
            lng: { type: 'number', description: 'Longitude of the centre point' },
            poly: { type: 'string', description: 'Lat/lng pairs defining a polygon' },
            date: { type: 'string', description: 'Specific month (YYYY-MM)' }
          }
        }
      },
      {
        name: 'get_stop_searches_by_location',
        description: 'Retrieve stop and searches at a specific location by ID',
        inputSchema: {
          type: 'object',
          properties: {
            location_id: { type: 'number', description: 'The ID of the location' },
            date: { type: 'string', description: 'Specific month (YYYY-MM)' }
          },
          required: ['location_id']
        }
      },
      {
        name: 'get_stop_searches_no_location',
        description: 'Retrieve stop and searches that could not be mapped to a location',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            date: { type: 'string', description: 'Specific month (YYYY-MM)' }
          },
          required: ['force_id']
        }
      },
      {
        name: 'get_stop_searches_by_force',
        description: 'Retrieve stop and searches reported by a specific force',
        inputSchema: {
          type: 'object',
          properties: {
            force_id: { type: 'string', description: 'The unique identifier for the force' },
            date: { type: 'string', description: 'Specific month (YYYY-MM)' }
          },
          required: ['force_id']
        }
      }
    ];
  • The `makeApiRequest` helper function used by the handler to make HTTP GET requests to the police.uk API.
    // Helper function to make API requests to police.uk
    async function makeApiRequest(endpoint: string, params?: Record<string, any>) {
      const baseUrl = 'https://data.police.uk/api';
      const url = `${baseUrl}/${endpoint}`;
      
      try {
        const response = await axios.get(url, { params, timeout: 10000 });
        return response.data;
      } catch (error) {
        console.error(`API request failed: ${error}`);
        return null;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, and the description fails to disclose any behavioral traits beyond the basic capability. Missing details such as response format, pagination, rate limits, or data freshness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence, no unnecessary words. However, brevity comes at the cost of omitting useful details. Could include more context without becoming verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, and the description does not explain what outcomes are returned (e.g., format, fields). No guidance on required parameters or constraints (e.g., lat and lng must be used together). Incomplete for a tool with 5 optional parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers all 5 parameters with descriptions (100% coverage). The description adds minor value by indicating that parameters are organized into alternative query modes (lat/lng, polygon, location ID), but does not elaborate on parameter usage beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the action (Retrieve) and resource (outcomes), and specifies three distinct query methods (lat/lng, custom polygon, or location ID) which distinguishes it from sibling tools like get_crimes_at_location or get_outcomes_for_crime.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit when-to-use or when-not-to-use guidance relative to siblings. While the purpose is clear, the description does not mention alternatives or contexts where other tools (e.g., get_outcomes_for_crime) would be more appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dwain-barnes/police-uk-api-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server