diff --git a/src/main/java/org/eclipsefoundation/marketplace/model/MongoQuery.java b/src/main/java/org/eclipsefoundation/marketplace/model/MongoQuery.java
index c1ae7dc4431775ae7a9a499b8a816f1c8424bab7..4972ca632764105d12ca5bf5bc0ea6b9cdf49fe0 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/model/MongoQuery.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/model/MongoQuery.java
@@ -37,7 +37,7 @@ public class MongoQuery<T> {
 	private static final Logger LOGGER = LoggerFactory.getLogger(MongoQuery.class);
 
 	private CachingService<List<T>> cache;
-	private RequestWrapper qps;
+	private RequestWrapper wrapper;
 	private DtoFilter<T> dtoFilter;
 
 	private Bson filter;
@@ -45,8 +45,8 @@ public class MongoQuery<T> {
 	private SortOrder order;
 	private List<Bson> aggregates;
 
-	public MongoQuery(RequestWrapper qps, DtoFilter<T> dtoFilter, CachingService<List<T>> cache) {
-		this.qps = qps;
+	public MongoQuery(RequestWrapper wrapper, DtoFilter<T> dtoFilter, CachingService<List<T>> cache) {
+		this.wrapper = wrapper;
 		this.dtoFilter = dtoFilter;
 		this.cache = cache;
 		this.aggregates = new ArrayList<>();
@@ -68,10 +68,10 @@ public class MongoQuery<T> {
 
 		// get the filters for the current DTO
 		List<Bson> filters = new ArrayList<>();
-		filters.addAll(dtoFilter.getFilters(qps));
+		filters.addAll(dtoFilter.getFilters(wrapper));
 		
 		// get fields that make up the required fields to enable pagination and check
-		Optional<String> sortOpt = qps.getFirstParam(UrlParameterNames.SORT);
+		Optional<String> sortOpt = wrapper.getFirstParam(UrlParameterNames.SORT);
 		if (sortOpt.isPresent()) {
 			String sortVal = sortOpt.get();
 			// split sort string of `<fieldName> <SortOrder>`
@@ -86,7 +86,7 @@ public class MongoQuery<T> {
 		if (!filters.isEmpty()) {
 			this.filter = Filters.and(filters);
 		}
-		this.aggregates = dtoFilter.getAggregates(qps);
+		this.aggregates = dtoFilter.getAggregates(wrapper);
 		
 		if (LOGGER.isDebugEnabled()) {
 			LOGGER.debug("MongoDB query initialized with filter: {}", this.filter);
@@ -129,7 +129,7 @@ public class MongoQuery<T> {
 	 *         present and numeric, otherwise returns -1.
 	 */
 	public int getLimit() {
-		Optional<String> limitVal = qps.getFirstParam(UrlParameterNames.LIMIT);
+		Optional<String> limitVal = wrapper.getFirstParam(UrlParameterNames.LIMIT);
 		if (limitVal.isPresent() && StringUtils.isNumeric(limitVal.get())) {
 			return Integer.parseInt(limitVal.get());
 		}
@@ -137,7 +137,7 @@ public class MongoQuery<T> {
 	}
 
 	private void setSort(String sortField, String sortOrder, List<Bson> filters) {
-		Optional<String> lastOpt = qps.getFirstParam(UrlParameterNames.LAST_SEEN);
+		Optional<String> lastOpt = wrapper.getFirstParam(UrlParameterNames.LAST_SEEN);
 		
 		List<Sortable<?>> fields = SortableHelper.getSortableFields(getDocType());
 		Optional<Sortable<?>> fieldContainer = SortableHelper.getSortableFieldByName(fields, sortField);
@@ -186,21 +186,21 @@ public class MongoQuery<T> {
 	 * @return the docType
 	 */
 	public Class<T> getDocType() {
-		return (Class<T>) qps.getAttribute(AnnotationClassInjectionFilter.ATTRIBUTE_NAME).get();
+		return (Class<T>) wrapper.getAttribute(AnnotationClassInjectionFilter.ATTRIBUTE_NAME).get();
 	}
 
 	/**
-	 * @return the qps
+	 * @return the wrapper
 	 */
-	public RequestWrapper getQps() {
-		return qps;
+	public RequestWrapper getWrapper() {
+		return wrapper;
 	}
 
 	/**
-	 * @param qps the qps to set
+	 * @param wrapper the wrapper to set
 	 */
-	public void setQps(RequestWrapper qps) {
-		this.qps = qps;
+	public void setWrapper(RequestWrapper wrapper) {
+		this.wrapper = wrapper;
 	}
 
 	@Override
diff --git a/src/main/java/org/eclipsefoundation/marketplace/model/RequestWrapper.java b/src/main/java/org/eclipsefoundation/marketplace/model/RequestWrapper.java
index b6f103cbdf45f955bef4dbe16f053e97b554b392..9169035502b91b3fc9e2a0bb5f13efaf125f24e4 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/model/RequestWrapper.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/model/RequestWrapper.java
@@ -53,7 +53,7 @@ public class RequestWrapper {
 	/**
 	 * Retrieves the first value set in a list from the map for a given key.
 	 * 
-	 * @param params the parameter map containing the value
+	 * @param wrapper the parameter map containing the value
 	 * @param key    the key to retrieve the value for
 	 * @return the first value set in the parameter map for the given key, or null
 	 *         if absent.
@@ -73,7 +73,7 @@ public class RequestWrapper {
 	/**
 	 * Retrieves the value list from the map for a given key.
 	 * 
-	 * @param params the parameter map containing the values
+	 * @param wrapper the parameter map containing the values
 	 * @param key    the key to retrieve the values for
 	 * @return the value list for the given key if it exists, or an empty collection
 	 *         if none exists.
@@ -94,7 +94,7 @@ public class RequestWrapper {
 	 * Adds the given value for the given key, preserving previous values if they
 	 * exist.
 	 * 
-	 * @param params map containing parameters to update
+	 * @param wrapper map containing parameters to update
 	 * @param key    string key to add the value to, must not be null
 	 * @param value  the value to add to the key
 	 */
@@ -166,4 +166,14 @@ public class RequestWrapper {
 		}
 		return this.userAgent;
 	}
+	
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append("RequestWrapper [");
+		sb.append("ip=").append(request.getRemoteAddr());
+		sb.append(", uri=").append(request.getRequestURI());
+		sb.append(", params=").append(getParams());
+		return sb.toString();
+	}
 }
diff --git a/src/main/java/org/eclipsefoundation/marketplace/model/UserAgent.java b/src/main/java/org/eclipsefoundation/marketplace/model/UserAgent.java
index c5221f559ad3c70ea1fcaba8c04658791bfc6238..31700ed0f8b148c15504f8723fbc0407cf07f653 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/model/UserAgent.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/model/UserAgent.java
@@ -6,12 +6,14 @@
  */
 package org.eclipsefoundation.marketplace.model;
 
-import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.commons.lang3.StringUtils;
+import org.eclipsefoundation.marketplace.dto.Install;
+
 import com.google.common.base.Splitter;
 
 /**
@@ -21,7 +23,6 @@ import com.google.common.base.Splitter;
  * @author Martin Lowe
  */
 public class UserAgent {
-
 	/**
 	 * Matches a generic form of User-Agent strings with the following sections
 	 * 
@@ -32,16 +33,18 @@ public class UserAgent {
 	 * and version, separated by a slash.
 	 */
 	private static final Pattern USER_AGENT_PATTERN = Pattern
-			.compile("^(\\S+\\/\\S+)\\s?(?:\\(([^\\)]*?)\\)([^\\(]+(?:\\(([^\\)]*?)\\)([^\\(]+)?)?)?)?$");
+			.compile("^(\\S+\\/\\S+)\\s?(?:\\(([^\\)]*?)\\)(?:([^\\(]+)(?:\\(([^\\)]*+)\\))?)?)?$");
 	private static final String MPC_CLIENT_AGENT_NAME = "mpc";
 
-	private final String name;
-	private final String version;
+	private final String base;
+
+	private final String agentDeclaration;
 	private final String systemProperties;
-	private final String platform;
 	private final String platformDetails;
-	private final String enhancements;
+	private final String application;
 
+	private String name;
+	private String version;
 	private String javaVersion;
 	private String javaVendor;
 
@@ -49,8 +52,12 @@ public class UserAgent {
 	private String osVersion;
 	private String locale;
 
+	private String product;
+	private String productVersion;
 	private String eclipseVersion;
 
+	private boolean valid = true;
+
 	public UserAgent(String userAgent) {
 		Objects.requireNonNull(userAgent);
 
@@ -60,49 +67,52 @@ public class UserAgent {
 			throw new IllegalArgumentException("Passed string does not match an expected user-agent");
 		}
 
+		this.base = userAgent;
 		// get the name and version of the user agent
-		String agentDeclaration = m.group(0);
-		Iterator<String> it = Splitter.on('/').trimResults().split(agentDeclaration).iterator();
-		this.name = it.next();
-		this.version = it.next();
+		this.agentDeclaration = m.group(1);
+		List<String> agentProperties = Splitter.on('/').trimResults().limit(2).splitToList(agentDeclaration);
+		if (agentProperties.size() != 2) {
+			// should never throw as format is promised in regex
+			throw new IllegalArgumentException("Cannot read User-Agent name and version");
+		}
+		this.name = agentProperties.get(0);
+		this.version = agentProperties.get(1);
 
-		this.systemProperties = m.group(1);
-		this.platform = m.group(2);
+		this.systemProperties = m.group(2);
 		this.platformDetails = m.group(3);
-		this.enhancements = m.group(4);
-		if (MPC_CLIENT_AGENT_NAME.equalsIgnoreCase(name)) {
-			handleMpc();
+		this.application = m.group(4);
+		if (isFromMPC()) {
+			consumeSystemProps();
+			consumePlatformDetails();
 		}
 	}
 
-	/**
-	 * Breaks down the different MPC properties into explicit properties that can be
-	 * retrieved via getters built into the class. The expected format is defined
-	 * below:
-	 * 
-	 * <p>
-	 * {@code mpc/<mpc version> (Java <java version> <java vendor>; <os name> <os version> <os arch>; <locale>) <eclipse product>/<product version> (<eclipse application>)}
-	 * </p>
-	 */
-	private void handleMpc() {
+	private void consumeSystemProps() {
+		if (this.systemProperties == null) {
+			this.valid = false;
+			return;
+		}
 		// expected form: (Java <java version> <java vendor>; <os name> <os version> <os
 		// arch>; <locale>)
-		List<String> systemPropList = Splitter.on(';').splitToList(systemProperties);
+		List<String> systemPropList = Splitter.on(';').trimResults().splitToList(systemProperties);
 		if (systemPropList.size() != 3) {
-			// TODO throw exception?
+			this.valid = false;
+			return;
 		}
 		// expected form example: Java <java version> <vendor>
-		List<String> javaProps = Splitter.on(' ').limit(3).splitToList(systemPropList.get(0));
+		List<String> javaProps = Splitter.on(' ').trimResults().limit(3).splitToList(systemPropList.get(0));
 		if (javaProps.size() != 3) {
-			// TODO throw exception?
+			this.valid = false;
+			return;
 		}
 		this.javaVersion = javaProps.get(1);
 		this.javaVendor = javaProps.get(2);
 
 		// expected form: <OS name> <OS version> <OS arch>
-		List<String> systemProps = Splitter.on(' ').limit(3).splitToList(systemPropList.get(1));
+		List<String> systemProps = Splitter.on(' ').trimResults().limit(3).splitToList(systemPropList.get(1));
 		if (systemProps.size() != 3) {
-			// TODO throw exception?
+			this.valid = false;
+			return;
 		}
 		this.os = systemProps.get(0);
 		this.osVersion = systemProps.get(1);
@@ -110,36 +120,75 @@ public class UserAgent {
 		// get the current locale
 		this.locale = systemPropList.get(2);
 
-		// expected form: <eclipse product>/<product version>
-		List<String> platformProps = Splitter.on('/').limit(3).splitToList(platform);
+		// check if any fields are invalid
+		if (StringUtils.isBlank(javaVersion) || StringUtils.isBlank(javaVendor) || StringUtils.isBlank(os)
+				|| StringUtils.isBlank(locale)) {
+			this.valid = false;
+		}
+	}
+
+	private void consumePlatformDetails() {
+		if (this.platformDetails == null) {
+			this.valid = false;
+			return;
+		}
+		// expected form: <eclipse product>/<product version>/<platform version>
+		List<String> platformProps = Splitter.on('/').trimResults().limit(3).splitToList(platformDetails);
+		if (platformProps.size() != 3) {
+			this.valid = false;
+			return;
+		}
+		// get the properties and check if any fields are invalid
+		this.product = platformProps.get(0);
+		this.productVersion = platformProps.get(1);
+		this.eclipseVersion = platformProps.get(2);
+		if (StringUtils.isBlank(product) || StringUtils.isBlank(productVersion)
+				|| StringUtils.isBlank(eclipseVersion)) {
+			this.valid = false;
+		}
 	}
 
 	/**
-	 * @return the name
+	 * Generates a basic install record based on information based on the user agent
+	 * properties. This can only be used when the agent is detected as an MPC call
+	 * and the object is valid.
+	 * 
+	 * @return a basic populated install record without listing information, or null
+	 *         if the call doesn't originate from MPC or is missing information.
 	 */
-	public String getName() {
-		return name;
+	public Install generateInstallRecord() {
+		// check that agent comes from MPC and is valid before generating
+		if (!isValid()) {
+			return null;
+		}
+		// generate install record from fields
+		Install install = new Install();
+		install.setJavaVersion(javaVersion);
+		install.setLocale(locale);
+		install.setOs(os);
+		install.setEclipseVersion(eclipseVersion);
+		return install;
 	}
 
 	/**
-	 * @return the version
+	 * @return the base user agent string
 	 */
-	public String getVersion() {
-		return version;
+	public String getBase() {
+		return base;
 	}
 
 	/**
-	 * @return the version
+	 * @return the systemProperties
 	 */
 	public String getSystemProperties() {
 		return systemProperties;
 	}
 
 	/**
-	 * @return the platform
+	 * @return the agentDeclaration
 	 */
-	public String getPlatform() {
-		return platform;
+	public String getAgentDeclaration() {
+		return agentDeclaration;
 	}
 
 	/**
@@ -152,8 +201,22 @@ public class UserAgent {
 	/**
 	 * @return the enhancements
 	 */
-	public String getEnhancements() {
-		return enhancements;
+	public String getApplication() {
+		return application;
+	}
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @return the version
+	 */
+	public String getVersion() {
+		return version;
 	}
 
 	/**
@@ -191,4 +254,64 @@ public class UserAgent {
 		return locale;
 	}
 
+	/**
+	 * @return the product
+	 */
+	public String getProduct() {
+		return product;
+	}
+
+	/**
+	 * @return the productVersion
+	 */
+	public String getProductVersion() {
+		return productVersion;
+	}
+
+	/**
+	 * Checks whether the clients agent name matches expected value for the
+	 * marketplace client {@link MPC_CLIENT_AGENT_NAME}.
+	 * 
+	 * @return true if client agent name matches expected value, false otherwise.
+	 */
+	public boolean isFromMPC() {
+		return MPC_CLIENT_AGENT_NAME.equalsIgnoreCase(name);
+	}
+
+	/**
+	 * @return whether the current user agent is a valid MPC user agent
+	 */
+	public boolean isValid() {
+		return valid && isFromMPC();
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("UserAgent [name=");
+		builder.append(name);
+		builder.append(", version=");
+		builder.append(version);
+		builder.append(", javaVersion=");
+		builder.append(javaVersion);
+		builder.append(", javaVendor=");
+		builder.append(javaVendor);
+		builder.append(", os=");
+		builder.append(os);
+		builder.append(", osVersion=");
+		builder.append(osVersion);
+		builder.append(", locale=");
+		builder.append(locale);
+		builder.append(", eclipseVersion=");
+		builder.append(eclipseVersion);
+		builder.append(", product=");
+		builder.append(product);
+		builder.append(", productVersion=");
+		builder.append(productVersion);
+		builder.append(", application=");
+		builder.append(application);
+		builder.append("]");
+		return builder.toString();
+	}
+
 }
diff --git a/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java b/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java
index 9b84085298c5f3f6940c28d61d5aa8f33e49e75d..d5882ed583adfbe0a0cae50fbf7e081859db3a5f 100644
--- a/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java
+++ b/src/main/java/org/eclipsefoundation/marketplace/resource/InstallResource.java
@@ -20,11 +20,13 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 
 import org.eclipsefoundation.marketplace.dao.MongoDao;
 import org.eclipsefoundation.marketplace.dto.Install;
 import org.eclipsefoundation.marketplace.dto.filter.DtoFilter;
 import org.eclipsefoundation.marketplace.helper.StreamHelper;
+import org.eclipsefoundation.marketplace.model.Error;
 import org.eclipsefoundation.marketplace.model.MongoQuery;
 import org.eclipsefoundation.marketplace.model.RequestWrapper;
 import org.eclipsefoundation.marketplace.model.ResourceDataType;
@@ -50,7 +52,7 @@ public class InstallResource {
 	@Inject
 	MongoDao dao;
 	@Inject
-	RequestWrapper params;
+	RequestWrapper wrapper;
 	@Inject
 	DtoFilter<Install> dtoFilter;
 
@@ -59,7 +61,7 @@ public class InstallResource {
 	CachingService<Long> countCache;
 	@Inject
 	CachingService<List<Install>> installCache;
-	
+
 	/**
 	 * Endpoint for /listing/\<listingId\>/installs to retrieve install metrics for
 	 * a specific listing from the database.
@@ -70,9 +72,9 @@ public class InstallResource {
 	@GET
 	@Path("/{listingId}")
 	public Response selectInstallMetrics(@PathParam("listingId") String listingId) {
-		params.addParam(UrlParameterNames.ID, listingId);
-		MongoQuery<Install> q = new MongoQuery<>(params, dtoFilter, installCache);
-		Optional<Long> cachedResults = countCache.get(listingId, params,
+		wrapper.addParam(UrlParameterNames.ID, listingId);
+		MongoQuery<Install> q = new MongoQuery<>(wrapper, dtoFilter, installCache);
+		Optional<Long> cachedResults = countCache.get(listingId, wrapper,
 				() -> StreamHelper.awaitCompletionStage(dao.count(q)));
 		if (!cachedResults.isPresent()) {
 			LOGGER.error("Error while retrieving cached listing for ID {}", listingId);
@@ -94,11 +96,12 @@ public class InstallResource {
 	 */
 	@GET
 	@Path("/{listingId}/{version}")
-	public Response selectInstallMetrics(@PathParam("listingId") String listingId, @PathParam("version") String version) {
-		params.addParam(UrlParameterNames.ID, listingId);
-		params.addParam(UrlParameterNames.VERSION, version);
-		MongoQuery<Install> q = new MongoQuery<>(params, dtoFilter, installCache);
-		Optional<Long> cachedResults = countCache.get(getCompositeKey(listingId, version), params,
+	public Response selectInstallMetrics(@PathParam("listingId") String listingId,
+			@PathParam("version") String version) {
+		wrapper.addParam(UrlParameterNames.ID, listingId);
+		wrapper.addParam(UrlParameterNames.VERSION, version);
+		MongoQuery<Install> q = new MongoQuery<>(wrapper, dtoFilter, installCache);
+		Optional<Long> cachedResults = countCache.get(getCompositeKey(listingId, version), wrapper,
 				() -> StreamHelper.awaitCompletionStage(dao.count(q)));
 		if (!cachedResults.isPresent()) {
 			LOGGER.error("Error while retrieving cached listing for ID {}", listingId);
@@ -121,21 +124,39 @@ public class InstallResource {
 	@Path("/{listingId}/{version}")
 	public Response postInstallMetrics(@PathParam("listingId") String listingId, @PathParam("version") String version,
 			Install installDetails) {
-		// update the install details to reflect the current request
-		installDetails.setInstallDate(new Date(System.currentTimeMillis()));
-		installDetails.setListingId(listingId);
-		installDetails.setVersion(version);
+		Install record = null;
 		
+		// check that connection was opened by MPC, and check for install information
+		// from user agent
+		if (wrapper.getUserAgent().isValid()) {
+			record = wrapper.getUserAgent().generateInstallRecord();
+		} else if (wrapper.getUserAgent().isFromMPC()) {
+			if (installDetails == null) {
+				return new Error(Status.BAD_REQUEST, "Install data could not be read from request body")
+						.asResponse();
+			}
+			record = installDetails;
+		} else {
+			LOGGER.warn("Rebuffed request to post install from request: {}", wrapper);
+			return new Error(Status.FORBIDDEN, "Installs cannot be posted directly from consumer applications")
+					.asResponse();
+		}
+
+		// update the install details to reflect the current request
+		record.setInstallDate(new Date(System.currentTimeMillis()));
+		record.setListingId(listingId);
+		record.setVersion(version);
+
 		// create the query wrapper to pass to DB dao
-		MongoQuery<Install> q = new MongoQuery<>(params, dtoFilter, installCache);
+		MongoQuery<Install> q = new MongoQuery<>(wrapper, dtoFilter, installCache);
 
 		// add the object, and await the result
-		StreamHelper.awaitCompletionStage(dao.add(q, Arrays.asList(installDetails)));
+		StreamHelper.awaitCompletionStage(dao.add(q, Arrays.asList(record)));
 
 		// return the results as a response
 		return Response.ok().build();
 	}
-	
+
 	private String getCompositeKey(String listingId, String version) {
 		return listingId + ':' + version;
 	}
diff --git a/src/main/node/index.js b/src/main/node/index.js
index e0899796e7fce1255aac9fc2eb3dae077981821e..5bbf210026abd738c85dab42ab9d7d7e96a94763 100644
--- a/src/main/node/index.js
+++ b/src/main/node/index.js
@@ -1,4 +1,8 @@
 const axios = require('axios');
+const instance = axios.create({
+  timeout: 1000,
+  headers: {'User-Agent': 'mpc/0.0.0'}
+});
 const randomWords = require('random-words');
 const uuid = require('uuid');
 const argv = require('yargs')
@@ -68,7 +72,7 @@ function createListing(count) {
   
   console.log(`Generating listing ${count} of ${max}`);
   var json = generateJSON(uuid.v4());
-  axios.put(argv.s+"/listings/", json)
+  axios.post(argv.s+"/listings/", json)
     .then(() => {
       var installs = Math.floor(Math.random()*argv.i);
       console.log(`Generating ${installs} install records for listing '${json.id}'`);
@@ -82,7 +86,7 @@ function createCategory(count) {
     return;
   }
 
-  axios.put(argv.s+"/categories/", generateCategoryJSON(categoryIds[count++]))
+  instance.put(argv.s+"/categories/", generateCategoryJSON(categoryIds[count++]))
     .then(() => createCategory(count))
     .catch(err => console.log(err));
 }
@@ -92,7 +96,7 @@ function createMarket(count) {
     return;
   }
 
-  axios.put(argv.s+"/markets/", generateMarketJSON(marketIds[count++]))
+  instance.put(argv.s+"/markets/", generateMarketJSON(marketIds[count++]))
     .then(() => createMarket(count))
     .catch(err => console.log(err));
 }
@@ -102,7 +106,7 @@ function createInstall(curr, max, listing, callback) {
     return callback();
   }
   var json = generateInstallJSON(listing);
-  axios.post(`${argv.s}/installs/${json['listing_id']}/${json.version}`, json)
+  instance.post(`${argv.s}/installs/${json['listing_id']}/${json.version}`, json)
     .then(createInstall(curr+1,max,listing,callback))
     .catch(err => console.log(err));
 }
@@ -170,8 +174,8 @@ function generateMarketJSON(id) {
 
 function generateInstallJSON(listing) {
   var version = listing.versions[Math.floor(Math.random()*listing.versions.length)];
-  var javaVersions = javaVs.splice(javaVs.indexOf(version["min_java_version"]));
-  var eclipseVersions = eclipseVs.splice(eclipseVs.indexOf(version["eclipse_version"]));
+  var javaVersions = Array.from(javaVs).splice(javaVs.indexOf(version["min_java_version"]));
+  var eclipseVersions = Array.from(eclipseVs).splice(eclipseVs.indexOf(version["eclipse_version"]));
   
   return {
     "listing_id": listing.id,